Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
difflib.cpython-314.pyc1029 linesDownload Raw Back to __pycache__
1+
2��iH���Rt.ROt^RIHt^RIHt^RIH	t	]!RR4t3R	t!R4R4tR Rlt
Rt!R
R4tR!RltR"RltRtR#RltRtR#RltRtR$RltR]3RltRR]3RltRtRtRtRt!RR]4tRt R#)%ae5Module difflib -- helpers for computing deltas between objects.6 7Function get_close_matches(word, possibilities, n=3, cutoff=0.6):8    Use SequenceMatcher to return list of the best "good enough" matches.9 10Function context_diff(a, b):11    For two lists of strings, return a delta in context diff format.12 13Function ndiff(a, b):14    Return a delta: the difference between `a` and `b` (lists of strings).15 16Function restore(delta, which):17    Return one of the two sequences that generated an ndiff delta.18 19Function unified_diff(a, b):20    For two lists of strings, return a delta in unified diff format.21 22Class SequenceMatcher:23    A flexible class for comparing pairs of sequences of any type.24 25Class Differ:26    For producing human-readable deltas from sequences of lines of text.27 28Class HtmlDiff:29    For producing HTML side by side comparison with change highlights.30�SequenceMatcher�Differ�HtmlDiff�Match)�nlargest)�31namedtuple)�GenericAliasza b sizec�6�V'dRV,V,#R#)g@��?�)�matches�lengths&&�Lib\difflib.py�_calculate_ratior's��
��W�}�v�%�%��c�a�]tRt^,toRtRRltRtRtRtRt	RRlt32R	tR33tRRlt
RtR
tRt]!]4tRtVtR#)ra�34SequenceMatcher is a flexible class for comparing pairs of sequences of35any type, so long as the sequence elements are hashable.  The basic36algorithm predates, and is a little fancier than, an algorithm37published in the late 1980's by Ratcliff and Obershelp under the38hyperbolic name "gestalt pattern matching".  The basic idea is to find39the longest contiguous matching subsequence that contains no "junk"40elements (R-O doesn't address junk).  The same idea is then applied41recursively to the pieces of the sequences to the left and to the right42of the matching subsequence.  This does not yield minimal edit43sequences, but does tend to yield matches that "look right" to people.44 45SequenceMatcher tries to compute a "human-friendly diff" between two46sequences.  Unlike e.g. UNIX(tm) diff, the fundamental notion is the47longest *contiguous* & junk-free matching subsequence.  That's what48catches peoples' eyes.  The Windows(tm) windiff has another interesting49notion, pairing up elements that appear uniquely in each sequence.50That, and the method here, appear to yield more intuitive difference51reports than does diff.  This method appears to be the least vulnerable52to syncing up on blocks of "junk lines", though (like blank lines in53ordinary text files, or maybe "<P>" lines in HTML files).  That may be54because this is the only method of the 3 that has a *concept* of55"junk" <wink>.56 57Example, comparing two strings, and considering blanks to be "junk":58 59>>> s = SequenceMatcher(lambda x: x == " ",60...                     "private Thread currentThread;",61...                     "private volatile Thread currentThread;")62>>>63 64.ratio() returns a float in [0, 1], measuring the "similarity" of the65sequences.  As a rule of thumb, a .ratio() value over 0.6 means the66sequences are close matches:67 68>>> print(round(s.ratio(), 2))690.8770>>>71 72If you're only interested in where the sequences match,73.get_matching_blocks() is handy:74 75>>> for block in s.get_matching_blocks():76...     print("a[%d] and b[%d] match for %d elements" % block)77a[0] and b[0] match for 8 elements78a[8] and b[17] match for 21 elements79a[29] and b[38] match for 0 elements80 81Note that the last tuple returned by .get_matching_blocks() is always a82dummy, (len(a), len(b), 0), and this is the only case in which the last83tuple element (number of elements matched) is 0.84 85If you want to know how to change the first sequence into the second,86use .get_opcodes():87 88>>> for opcode in s.get_opcodes():89...     print("%6s a[%d:%d] b[%d:%d]" % opcode)90 equal a[0:8] b[0:8]91insert a[8:8] b[8:17]92 equal a[8:29] b[17:38]93 94See the Differ class for a fancy human-friendly file differencer, which95uses SequenceMatcher both to compare sequences of lines, and to compare96sequences of characters within similar (near-matching) lines.97 98See also function get_close_matches() in this module, which shows how99simple code building on SequenceMatcher can be used to do useful work.100 101Timing:  Basic R-O is cubic time worst case and quadratic time expected102case.  SequenceMatcher is quadratic time for the worst case and has103expected-case behavior dependent in a complicated way on how many104elements the sequences have in common; best case time is linear.105Nc�\�WnR;VnVnW@nVP	W#4R#)a�Construct a SequenceMatcher.106 107Optional arg isjunk is None (the default), or a one-argument108function that takes a sequence element and returns true iff the109element is junk.  None is equivalent to passing "lambda x: 0", i.e.110no elements are considered to be junk.  For example, pass111    lambda x: x in " \t"112if you're comparing lines as sequences of characters, and don't113want to synch up on blanks or hard tabs.114 115Optional arg a is the first of two sequences to be compared.  By116default, an empty string.  The elements of a must be hashable.  See117also .set_seqs() and .set_seq1().118 119Optional arg b is the second of two sequences to be compared.  By120default, an empty string.  The elements of b must be hashable. See121also .set_seqs() and .set_seq2().122 123Optional arg autojunk should be set to False to disable the124"automatic junk heuristic" that treats popular elements as junk125(see module documentation for more information).126N)�isjunk�a�b�autojunk�set_seqs)�selfrrrrs&&&&&r�__init__�SequenceMatcher.__init__xs)��v�������� �
��
�
�a�rc�J�VPV4VPV4R#)zsSet the two sequences to be compared.127 128>>> s = SequenceMatcher()129>>> s.set_seqs("abcd", "bcde")130>>> s.ratio()1310.75132N)�set_seq1�set_seq2)rrrs&&&rr�SequenceMatcher.set_seqs�s��	
�
�
�a���
�
�a�rc�P�WPJdR#WnR;VnVnR#)a�Set the first sequence to be compared.133 134The second sequence to be compared is not changed.135 136>>> s = SequenceMatcher(None, "abcd", "bcde")137>>> s.ratio()1380.75139>>> s.set_seq1("bcde")140>>> s.ratio()1411.0142>>>143 144SequenceMatcher computes and caches detailed information about the145second sequence, so if you want to compare one sequence S against146many sequences, use .set_seq2(S) once and call .set_seq1(x)147repeatedly for each of the other sequences.148 149See also set_seqs() and set_seq2().150N)r�matching_blocks�opcodes)rrs&&rr�SequenceMatcher.set_seq1�s$��*
���;����.2�2���t�|rc�~�WPJdR#WnR;VnVnRVnVP	4R#)a�Set the second sequence to be compared.151 152The first sequence to be compared is not changed.153 154>>> s = SequenceMatcher(None, "abcd", "bcde")155>>> s.ratio()1560.75157>>> s.set_seq2("abcd")158>>> s.ratio()1591.0160>>>161 162SequenceMatcher computes and caches detailed information about the163second sequence, so if you want to compare one sequence S against164many sequences, use .set_seq2(S) once and call .set_seq1(x)165repeatedly for each of the other sequences.166 167See also set_seqs() and set_seq1().168N)rr r!�169fullbcount�_SequenceMatcher__chain_b)rrs&&rr�SequenceMatcher.set_seq2�s5��*
���;����.2�2���t�|�������rc��VPp/;Vnp\V4F(wr4VPV.4pVP	V4K*	\4;VnpVPpV'dDVP4F$pV!V4'gKVPV4K&	VFpW$K	\4;Vn170p\V4p	VP'dcV	^�8�dZV	^d,^,p171VP4F(wrK\V4V1728�gKVPV4K*	VFpW$K	R#R#R#)��N)r�b2j�	enumerate�173setdefault�append�set�bjunkr�keys�add�bpopular�lenr�items)rrr)�i�elt�indices�junkr�popular�n�ntest�idxss&           r�	__chain_b�SequenceMatcher.__chain_b174s
��
�F�F������3���l�F�A��n�n�S�"�-�G��N�N�1��#�175 �E�!��176�T�������x�x�z���#�;�;��H�H�S�M�"����H��#&�%�'��
����F���=�=�=�Q�#�X���H�q�L�E� �Y�Y�[�	���t�9�u�$��K�K��$�)����H��&�=rc�"�VPVPVPVPP3wrVrxVf\V4pVf\V4pY^r�p	/p.p
\
W4F�pVPp/pVPW^,V
4F[pVV8dKVV8�dMJV!V^,177^4^,;pVV&VV8�gK:VV,178^,VV,179^,Tr�p	K]	TpK�	W�8�d_W�8�dYV!Wj^,180,4'g>WY^,181,Wj^,182,8XdV	^,183V184^,185V^,r�p	KdW�,V8dUW�,V8dHV!WjV,,4'g-WYV,,WjV,,8XdV^,
pKaW�8�d_W�8�dYV!Wj^,186,4'd>WY^,187,Wj^,188,8XdV	^,189V190^,191V^,r�p	KdW�,V8dUW�,V8dHV!WjV,,4'd-WYV,,WjV,,8XdV^,pKa\W�V4#)a9Find longest matching block in a[alo:ahi] and b[blo:bhi].192 193By default it will find the longest match in the entirety of a and b.194 195If isjunk is not defined:196 197Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where198    alo <= i <= i+k <= ahi199    blo <= j <= j+k <= bhi200and for all (i',j',k') meeting those conditions,201    k >= k'202    i <= i'203    and if i == i', j <= j'204 205In other words, of all maximal matching blocks, return one that206starts earliest in a, and of all those maximal matching blocks that207start earliest in a, return the one that starts earliest in b.208 209>>> s = SequenceMatcher(None, " abcd", "abcd abcd")210>>> s.find_longest_match(0, 5, 0, 9)211Match(a=0, b=4, size=5)212 213If isjunk is defined, first the longest matching block is214determined as above, but with the additional restriction that no215junk element appears in the block.  Then that block is extended as216far as possible by matching (only) junk elements on both sides.  So217the resulting block never matches on junk except as identical junk218happens to be adjacent to an "interesting" match.219 220Here's the same example as before, but considering blanks to be221junk.  That prevents " abcd" from matching the " abcd" at the tail222end of the second sequence directly.  Instead only the "abcd" can223match, and matches the leftmost "abcd" in the second sequence:224 225>>> s = SequenceMatcher(lambda x: x==" ", " abcd", "abcd abcd")226>>> s.find_longest_match(0, 5, 0, 9)227Match(a=1, b=0, size=4)228 229If no blocks match, return (alo, blo, 0).230 231>>> s = SequenceMatcher(None, "ab", "c")232>>> s.find_longest_match(0, 2, 0, 1)233Match(a=0, b=0, size=0)234)	rrr)r.�__contains__r2�range�getr)r�alo�ahi�blo�bhirrr)�isbjunk�besti�bestj�bestsize�j2len�nothingr4�j2lenget�newj2len�j�ks&&&&&              r�find_longest_match�"SequenceMatcher.find_longest_match1s��t"�V�V�T�V�V�T�X�X�t�z�z�7N�7N�N���c��;��a�&�C��;��a�&�C�!$�1�h�������s��A��y�y�H��H��W�W�Q�T�7�+���s�7����8��"*�1�Q�3��"2�Q�"6�6��H�Q�K��x�<�-.�q�S��U�A�a�C��E�1�(�E�(�,��E�!�(�k�e�k��!�!�G�*�%�%��a��j�A�A�g�J�&�%*�1�W�e�A�g�x��z�(�E�(��n�s�"�u�~��';��!�(�N�+�,�,��h���1�8�^�#4�4���M�H��k�e�k��a�a��j�!�!��a��j�A�A�g�J�&�%*�1�W�e�A�g�x��z�(�E�(��n�s�"�u�~��';��a�h��'�(�(��h���1�8�^�#4�4��!�|�H��U�8�,�,rc��VPe
VP#\VP4\VP4r!^V^V3.p.pV'd�VP	4wrVrxVPWVWx4;wr�r�V'gK;VP
V4WY8dWz8dVP
WYWz34W�,V8gKzW�,V8gK�VP
W�,WjV,V34K�VP4^;p
;r�.pVFLwpppW�,V8XdW�,V8XdVV,
pK,V'dVP
W�V34TTTr�p
KN	V'dVP
W�V34VP
W^34\\\PV44VnVP#)a�Return list of triples describing matching subsequences.235 236Each triple is of the form (i, j, n), and means that237a[i:i+n] == b[j:j+n].  The triples are monotonically increasing in238i and in j.  New in Python 2.5, it's also guaranteed that if239(i, j, n) and (i', j', n') are adjacent triples in the list, and240the second is not the last triple in the list, then i+n != i' or241j+n != j'.  IOW, adjacent triples never describe adjacent equal242blocks.243 244The last triple is a dummy, (len(a), len(b), 0), and is the only245triple with n==0.246 247>>> s = SequenceMatcher(None, "abxcd", "abcd")248>>> list(s.get_matching_blocks())249[Match(a=0, b=0, size=2), Match(a=3, b=2, size=2), Match(a=5, b=4, size=0)]250)r r2rr�poprPr,�sort�list�mapr�_make)r�la�lb�queuer rBrCrDrEr4rNrO�x�i1�j1�k1�non_adjacent�i2�j2�k2s&                   r�get_matching_blocks�#SequenceMatcher.get_matching_blocks�s���&���+��'�'�'��T�V�V��c�$�&�&�k�B��R��B�� �����!&�����C�c��1�1�#�C�E�E�G�A�!��q��&�&�q�)��7�s�w��L�L�#�#�!1�2��3��9���s���L�L�!�#�s�a�C��!5�6�����251����R���)�J�B��B��w�"�}���B���b���252� �'�'����5���R����*��������-����b�a�[�*�#�C����\�$B�C����#�#�#rc�\�VPe
VP#^;r.;VnpVP4FqwrEpRpW8d253W%8dRpMW8dRpMW%8dRpV'dVPWqWBV34WF,WV,r!V'gK]VPRWAWR34Ks	V#)a�Return list of 5-tuples describing how to turn a into b.254 255Each tuple is of the form (tag, i1, i2, j1, j2).  The first tuple256has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the257tuple preceding it, and likewise for j1 == the previous j2.258 259The tags are strings, with these meanings:260 261'replace':  a[i1:i2] should be replaced by b[j1:j2]262'delete':   a[i1:i2] should be deleted.263            Note that j1==j2 in this case.264'insert':   b[j1:j2] should be inserted at a[i1:i1].265            Note that i1==i2 in this case.266'equal':    a[i1:i2] == b[j1:j2]267 268>>> a = "qabxcd"269>>> b = "abycdf"270>>> s = SequenceMatcher(None, a, b)271>>> for tag, i1, i2, j1, j2 in s.get_opcodes():272...    print(("%7s a[%d:%d] (%s) b[%d:%d] (%s)" %273...           (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2])))274 delete a[0:1] (q) b[0:0] ()275  equal a[1:3] (ab) b[0:2] (ab)276replace a[3:4] (x) b[2:3] (y)277  equal a[4:6] (cd) b[3:5] (cd)278 insert a[6:6] () b[5:6] (f)279��replace�delete�insert�equal)r!rcr,)rr4rN�answer�ai�bj�size�tags&       r�get_opcodes�SequenceMatcher.get_opcodes�s���:�<�<�#��<�<���	�� "�"���v� �4�4�6�L�B�D��C��v�!�&�������������
�
���r�2�4��7�B�G�q��t��
�
����6�8�'7�(�
rc#�"�VP4pV'gR.pV^,^,R8Xd8V^,wr4rVpV\WEV,2804V\WgV,2814V3V^&VR,^,R8Xd7VR,wr4rVpW4\WTV,4V\WvV,43VR&W,p.p	VF�wr4rVpVR8XdlWT,282V8�d_V	PW4\WTV,4V\WvV,434V	x�.p	\WEV,2834\WgV,2844rdV	PW4WVV34K�	V	'd.\	V	4^8XdV	^,^,R8XgV	x�R#R#R#5i)a9Isolate change clusters by eliminating ranges with no changes.285 286Return a generator of groups with up to n lines of context.287Each group is in the same format as returned by get_opcodes().288 289>>> from pprint import pprint290>>> a = list(map(str, range(1,40)))291>>> b = a[:]292>>> b[8:8] = ['i']     # Make an insertion293>>> b[20] += 'x'       # Make a replacement294>>> b[23:28] = []      # Make a deletion295>>> b[30] += 'y'       # Make another replacement296>>> pprint(list(SequenceMatcher(None,a,b).get_grouped_opcodes()))297[[('equal', 5, 8, 5, 8), ('insert', 8, 8, 8, 9), ('equal', 8, 11, 9, 12)],298 [('equal', 16, 19, 17, 20),299  ('replace', 19, 20, 20, 21),300  ('equal', 20, 22, 21, 23),301  ('delete', 22, 27, 23, 23),302  ('equal', 27, 30, 23, 26)],303 [('equal', 31, 34, 27, 30),304  ('replace', 34, 35, 30, 31),305  ('equal', 35, 38, 31, 34)]]306rjN)rj��rsrt�����)rp�max�minr,r2)307rr9�codesror\r`r]ra�nn�groups308&&        r�get_grouped_opcodes�#SequenceMatcher.get_grouped_opcodes#sX���2� � �"���*�+�E���8�A�;�'�!�"'��(��C�R�R��C��q�D�M�2�s�2�!�t�}�b�@�E�!�H���9�Q�<�7�"�"'��)��C�R�R���R�A����C��q�D�M�A�E�"�I�
�U����#(��C�R�R��g�~�"�%�"�*����c�s�2�!�t�}�b�#�b�Q�$�-�H�I������R�A����B�1��
�B��L�L�#�2�2�.�/�$)��#�e�*�a�-�E�!�H�Q�K�7�,B��K�-C�5�s�EF	�/F	c��\RVP444p\V\VP4\VP3094,4#)aRReturn a measure of the sequences' similarity (float in [0,1]).310 311Where T is the total number of elements in both sequences, and312M is the number of matches, this is 2.0*M / T.313Note that this is 1 if the sequences are identical, and 0 if314they have nothing in common.315 316.ratio() is expensive to compute if you haven't already computed317.get_matching_blocks() or .get_opcodes(), in which case you may318want to try .quick_ratio() or .real_quick_ratio() first to get an319upper bound.320 321>>> s = SequenceMatcher(None, "abcd", "bcde")322>>> s.ratio()3230.75324>>> s.quick_ratio()3250.75326>>> s.real_quick_ratio()3271.0328c3�2"�TF
qR,x�K	R#5i)rtNrur)�.0�triples& r�	<genexpr>�(SequenceMatcher.ratio.<locals>.<genexpr>ks���J�/I�V�R�j�j�/I�s�)�sumrcrr2rr)rrs& r�ratio�SequenceMatcher.ratioUs?��,�J�t�/G�/G�/I�J�J�����T�V�V��s�4�6�6�{�)B�C�Crc���VPf8/;VnpVPFpVPV^4^,W&K 	VPp/pVP^rTVPFIpV!V4'd329W2,pMVPV^4pV^,330W2&V^8�gK@V^,pKK	\V\
VP4\
VP4,4#)z�Return an upper bound on ratio() relatively quickly.331 332This isn't defined beyond that it is an upper bound on .ratio(), and333is faster to compute.334)r$rrAr?rrr2)rr$r5�avail�availhasr�numbs&      r�quick_ratio�SequenceMatcher.quick_rations����?�?�"�+-�-�D�O�j��v�v��",�.�.��a�"8�1�"<�335����_�_�336���!�.�.��'��6�6�C���}�}��z��!�~�~�c�1�-�����E�J��a�x�!�A�+��� ���T�V�V��s�4�6�6�{�)B�C�Crc��\VP4\VP4r!\\	W4W,4#)z�Return an upper bound on ratio() very quickly.337 338This isn't defined beyond that it is an upper bound on .ratio(), and339is faster to compute than either .ratio() or .quick_ratio().340)r2rrrrw)rrXrYs&  r�real_quick_ratio� SequenceMatcher.real_quick_ratio�s0���T�V�V��c�$�&�&�k�B� ��B��R�W�5�5r)341rrrr)r.r1r$rr r!)NrfrfT)rsNrsN)�)�__name__�342__module__�__qualname__�__firstlineno__�__doc__rrrrr%rPrcrpr{r�r�r��classmethodr�__class_getitem__�__static_attributes__�__classdictcell__��
__classdict__s@rrr,s`����H�T>�@343�3�4�X%�Nr-�hE$�N5�n0�dD�2D�:3446�$�L�1�rc���V^8�g\RV:24hRTu;8:dR8:gM\RV:24h.p\4pVPV4VFzpVPV4VP	4V8�gK+VP4V8�gKBVP
4V8�gKYVPVP
4V34K|	\W$4pVUUu.uFwrvVNK		upp#uuppi)awUse SequenceMatcher to return list of the best "good enough" matches.345 346word is a sequence for which close matches are desired (typically a347string).348 349possibilities is a list of sequences against which to match word350(typically a list of strings).351 352Optional arg n (default 3) is the maximum number of close matches to353return.  n must be > 0.354 355Optional arg cutoff (default 0.6) is a float in [0, 1].  Possibilities356that don't score at least that similar to word are ignored.357 358The best (no more than n) matches among the possibilities are returned359in a list, sorted by similarity score, most similar first.360 361>>> get_close_matches("appel", ["ape", "apple", "peach", "puppy"])362['apple', 'ape']363>>> import keyword as _keyword364>>> get_close_matches("wheel", _keyword.kwlist)365['while']366>>> get_close_matches("Apple", _keyword.kwlist)367[]368>>> get_close_matches("accept", _keyword.kwlist)369['except']370zn must be > 0: gr371zcutoff must be in [0.0, 1.0]: )	�372ValueErrorrrrr�r�r�r,�	_nlargest)�word�
possibilitiesr9�cutoff�result�sr[�scores&&&&    r�get_close_matchesr��s���:
��6���3�4�4��&��C���v�G�H�H�
�F���A��J�J�t��
��	�373�374�1�
�����6�)��=�=�?�f�$��7�7�9����M�M�1�7�7�9�a�.�)���q�
!�F�$�%�f�(�%�A�f�%�%��%s�$
C5c�D�RPR\W444#)zAReplace whitespace with the original whitespace characters in `s`rfc3�h"�TF(wrVR8XdVP4'dTMTx�K*	R#5i)� N)�isspace)r�c�tag_cs&  rr��$_keep_original_ws.<locals>.<genexpr>�s.����%�H�A��c�\�a�i�i�k�k��u�4�%�s�#2�2)�join�zip)r��tag_ss&&r�_keep_original_wsr��s$��
�7�7���A�
���rc�Ra�]tRtRtoRtRRltRtRtRtRt	R	t375R376tRtVt
R#)
ri�a�377Differ is a class for comparing sequences of lines of text, and378producing human-readable differences or deltas.  Differ uses379SequenceMatcher both to compare sequences of lines, and to compare380sequences of characters within similar (near-matching) lines.381 382Each line of a Differ delta begins with a two-letter code:383 384    '- '    line unique to sequence 1385    '+ '    line unique to sequence 2386    '  '    line common to both sequences387    '? '    line not present in either input sequence388 389Lines beginning with '? ' attempt to guide the eye to intraline390differences, and were not present in either input sequence.  These lines391can be confusing if the sequences contain tab characters.392 393Note that Differ makes no claim to produce a *minimal* diff.  To the394contrary, minimal diffs are often counter-intuitive, because they synch395up anywhere possible, sometimes accidental matches 100 pages apart.396Restricting synch points to contiguous matches preserves some notion of397locality, at the occasional cost of producing a longer diff.398 399Example: Comparing two texts.400 401First we set up the texts, sequences of individual single-line strings402ending with newlines (such sequences can also be obtained from the403`readlines()` method of file-like objects):404 405>>> text1 = '''  1. Beautiful is better than ugly.406...   2. Explicit is better than implicit.407...   3. Simple is better than complex.408...   4. Complex is better than complicated.409... '''.splitlines(keepends=True)410>>> len(text1)4114412>>> text1[0][-1]413'\n'414>>> text2 = '''  1. Beautiful is better than ugly.415...   3.   Simple is better than complex.416...   4. Complicated is better than complex.417...   5. Flat is better than nested.418... '''.splitlines(keepends=True)419 420Next we instantiate a Differ object:421 422>>> d = Differ()423 424Note that when instantiating a Differ object we may pass functions to425filter out line and character 'junk'.  See Differ.__init__ for details.426 427Finally, we compare the two:428 429>>> result = list(d.compare(text1, text2))430 431'result' is a list of strings, so let's pretty-print it:432 433>>> from pprint import pprint as _pprint434>>> _pprint(result)435['    1. Beautiful is better than ugly.\n',436 '-   2. Explicit is better than implicit.\n',437 '-   3. Simple is better than complex.\n',438 '+   3.   Simple is better than complex.\n',439 '?     ++\n',440 '-   4. Complex is better than complicated.\n',441 '?            ^                     ---- ^\n',442 '+   4. Complicated is better than complex.\n',443 '?           ++++ ^                      ^\n',444 '+   5. Flat is better than nested.\n']445 446As a single multi-line string it looks like this:447 448>>> print(''.join(result), end="")449    1. Beautiful is better than ugly.450-   2. Explicit is better than implicit.451-   3. Simple is better than complex.452+   3.   Simple is better than complex.453?     ++454-   4. Complex is better than complicated.455?            ^                     ---- ^456+   4. Complicated is better than complex.457?           ++++ ^                      ^458+   5. Flat is better than nested.459Nc��WnW nR#)aU460Construct a text differencer, with optional filters.461 462The two optional keyword parameters are for filter functions:463 464- `linejunk`: A function that should accept a single string argument,465  and return true iff the string is junk. The module-level function466  `IS_LINE_JUNK` may be used to filter out lines without visible467  characters, except for at most one splat ('#').  It is recommended468  to leave linejunk None; the underlying SequenceMatcher class has469  an adaptive notion of "noise" lines that's better than any static470  definition the author has ever been able to craft.471 472- `charjunk`: A function that should accept a string of length 1. The473  module-level function `IS_CHARACTER_JUNK` may be used to filter out474  whitespace characters (a blank or tab; **note**: bad idea to include475  newline in this!).  Use of IS_CHARACTER_JUNK is recommended.476N��linejunk�charjunk)rr�r�s&&&rr�Differ.__init__*s��(!�
� �
rc	#�~"�\VPW4pVP4F�wrErgpVR8XdVPWWbWx4p	M`VR8XdVP	RWV4p	MEVR8XdVP	RW'V4p	M*VR8XdVP	RWV4p	M\RV:24hT	R	jx�L477K�	R	#L4785i)479aY480Compare two sequences of lines; generate the resulting delta.481 482Each sequence must contain individual single-line strings ending with483newlines. Such sequences can be obtained from the `readlines()` method484of file-like objects.  The delta generated also consists of newline-485terminated strings, ready to be printed as-is via the writelines()486method of a file-like object.487 488Example:489 490>>> print(''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(True),491...                                'ore\ntree\nemu\n'.splitlines(True))),492...       end="")493- one494?  ^495+ ore496?  ^497- two498- three499?  -500+ tree501+ emu502rgrh�-ri�+rjr��unknown tag N)rr�rp�_fancy_replace�_dumpr�)503rrr�cruncherrorBrCrDrE�gs504&&&       r�compare�Differ.compareAs����4#�4�=�=�!�7��'/�';�';�'=�#�C�c���i���'�'����A������J�J�s�A�C�0������J�J�s�A�C�0������J�J�s�A�C�0�� �S�!:�;�;��L�L�(>�
�s�B.B=�0B;�1B=c#�T"�\W44FpV:RW%,:2x�K	R#5i)z4Generate comparison results for a same-tagged range.r�N)r@)rror[�lo�hir4s&&&&& rr��Differ._dumpjs ����r��A� �!�$�'�'��s�&(c#�"�W#8dWV8gQhWe,505W2,5068d(VPRWEV4pVPRWV4pM&VPRWV4pVPRWEV4pWx3F
p	T	Rjx�L507K	R#L5085i)r�r�N)r�)509rrrBrCrrDrE�first�secondr�s510&&&&&&&   r�_plain_replace�Differ._plain_replaceos�����y�S�Y�&�&��9�s�y� ��Z�Z��Q�S�1�E��Z�Z��Q�S�1�F��Z�Z��Q�S�1�E��Z�Z��Q�S�1�F���A��L�L���s�A:B	�<B�=B	c	#�"�Rp\VP4pVPp	VPp511VPp^512pR;r�Y%pp\WV4EFpVP
VV,4VVV,513,p\\VV,514V4\VV,^,V44pV'gEM�TpVFOpVPVV,4V	!4V8�gK)V515!4V8�gK7V!4V8�gKETTV!4pr�KQ	V
fK�VPWV
VVV4Rjx�L516W,WN,ppVV8wd�R;ppVPVV4VP4F�wpppppVV,517VV,518p pVR8Xd#VRV,,
pVRV ,,
pKDVR8XdVRV,,
pK]VR8XdVR	V ,,
pKvVR5198Xd#VRV,,
pVRV ,,
pK�\RV:24h	VPVVVV4Rjx�L520MR
V,x�V
^,V^,ppR;r�EK	VPWVVVV4Rjx�L521R#ELSLLL5i)a�522When replacing one block of lines with another, search the blocks523for *similar* lines; the best-matching pair (if any) is used as a524synch point, and intraline difference marking is done on the525similar pair. Lots of work, but often worth it.526 527Example:528 529>>> d = Differ()530>>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,531...                            ['abcdefGhijkl\n'], 0, 1)532>>> print(''.join(results), end="")533- abcDefghiJkl534?    ^  ^  ^535+ abcdefGhijkl536?    ^  ^  ^537gwJ���?Nrfrg�^rhr�rir�rjr�r��  )rr�r�r�r�r@rrvrwr�
_fancy_helperrrpr��_qformat)!rrrBrCrrDrEr�r��crqr�cqr�cr�WINDOW�best_i�best_j�dump_i�dump_jrN�aequiv�arange�538best_ratior4�aelt�belt�atags�btagsro�ai1�ai2�bj1�bj2rXrYs!&&&&&&&                          rr��Differ._fancy_replace}s����4��"�4�=�=�1���(�(���"�"��
�^�^�����������s��A����a��d�#��A��G�_�F��3�v����7��v����2�C�8�:�F����J����!�!�!�A�$�'��F�Z�'��%�*�,��$��+�12�A�r�t�J�F�J���~���)�)�!�V�*+�V�V�=�
=�
=���A�I�$�D��t�|� "�"����!�!�$��-�/7�/C�/C�/E�+�C��c�3�� �3�Y��c�	��B��i�'���r��)����r��)�������r��)�������r��)�������r��)����r��)��(�S�)B�C�C�0F� �=�=��t�U�E�B�B�B��T�k�!�#�a�Z��!��F�F�"�"�F�V�g!�l�%�%�a��&'���6�	6�	6�=
=�,C�	6�sJ�C#J�*	J�8	J�,J�2J�3DJ�;J�<AJ�>J539�?J�J�540Jc#��"�.pW#8d/WV8dVPWW4WV4pM-VPRWV4pMWV8dVPRWEV4pTRjx�L541R#L5i)r�r�N)r�r�)rrrBrCrrDrEr�s&&&&&&& rr��Differ._fancy_helper�sX������9��y��'�'����A���J�J�s�A�C�0��
�Y��542�543�3���,�A����s�AA �A�A c#��"�\W4P4p\W$4P4pRV,x�V'd	RVR2x�RV,x�V'dRVR2x�R#R#5i)a:544Format "?" output and deal with tabs.545 546Example:547 548>>> d = Differ()549>>> results = d._qformat('\tabcDefghiJkl\n', '\tabcdefGhijkl\n',550...                      '  ^ ^  ^      ', '  ^ ^  ^      ')551>>> for line in results: print(repr(line))552...553'- \tabcDefghiJkl\n'554'? \t ^ ^  ^\n'555'+ \tabcdefGhijkl\n'556'? \t ^ ^  ^\n'557�- z? �558�+ N)r��rstrip)r�aline�bliner�r�s&&&&&rr��Differ._qformat�sh��� "�%�/�6�6�8��!�%�/�6�6�8���U�l����u�g�R�.� ��U�l����u�g�R�.� ��s�A A/�#A/)r�r�)NN)r�r�r�r�r�rr�r�r�r�r�r�r�r�r�s@rrr�s7����S�j!�.'�R(�559�Z6�x560�!�!rNc�D�VfVP4R9#V!V4RJ#)z�561Return True for ignorable line: if `line` is blank or contains a single '#'.562 563Examples:564 565>>> IS_LINE_JUNK('\n')566True567>>> IS_LINE_JUNK('  #   \n')568True569>>> IS_LINE_JUNK('hello\n')570False571N�#)�strip)�line�pats&&r�IS_LINE_JUNKr�s+���{��z�z�|�s�"�"��t�9�D� � rc�572�W9#)z�573Return True for ignorable character: iff `ch` is a space or tab.574 575Examples:576 577>>> IS_CHARACTER_JUNK(' ')578True579>>> IS_CHARACTER_JUNK('\t')580True581>>> IS_CHARACTER_JUNK('\n')582False583>>> IS_CHARACTER_JUNK('x')584False585r)�ch�wss&&r�IS_CHARACTER_JUNKr�&s�� �8�Orc��V^,pW,586pV^8XdRPV4#V'g587V^,pRPW#4#�z Convert range to the "ed" formatz{}z{},{}��format��start�stop�	beginningr
s&&  r�_format_range_unifiedr�=sE����	�I�
�\�F�
��{��{�{�9�%�%���Q��	��>�>�)�,�,rc	#��"�\WW#WEV4Rp\RW4PV4EF2p	V'gaRpV'dRPV4MRp588V'dRPV4MRpRPW*V4x�RPW;V4x�V	^,V	R
,r�\	V^,V
^,4p\	V^,V
^,4pRPW�V4x�V	FgwpppppVR	8XdVVVFpR589V,x�K	K)VR9dVVVFpRV,x�K	VR9gKPVVVFpRV,x�K	Ki	EK5	R#5i)a.590Compare two sequences of lines; generate the delta as a unified diff.591 592Unified diffs are a compact way of showing line changes and a few593lines of context.  The number of context lines is set by 'n' which594defaults to three.595 596By default, the diff control lines (those with ---, +++, or @@) are597created with a trailing newline.  This is helpful so that inputs598created from file.readlines() result in diffs that are suitable for599file.writelines() since both the inputs and outputs have trailing600newlines.601 602For inputs that do not have trailing newlines, set the lineterm603argument to "" so that the output will be uniformly newline free.604 605The unidiff format normally has a header for filenames and modification606times.  Any or all of these may be specified using strings for607'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.608The modification times are normally expressed in the ISO 8601 format.609 610Example:611 612>>> for line in unified_diff('one two three four'.split(),613...             'zero one tree four'.split(), 'Original', 'Current',614...             '2005-01-26 23:30:50', '2010-04-02 10:20:52',615...             lineterm=''):616...     print(line)                 # doctest: +NORMALIZE_WHITESPACE617--- Original        2005-01-26 23:30:50618+++ Current         2010-04-02 10:20:52619@@ -1,4 +1,4 @@620+zero621 one622-two623-three624+tree625 four626FNT�	{}rf�627--- {}{}{}z628+++ {}{}{}z@@ -{} +{} @@{}rjr�r�r�ru>rhrg>rirg)�_check_typesrr{r�r�)rr�fromfile�tofile�fromfiledate�629tofiledater9�lineterm�startedrz�fromdate�todater��last�file1_range�file2_rangeror\r`r]rar�s&&&&&&&&              r�unified_diffrHsS���R��x��8�L��G� ��a�*�>�>�q�A����G�6B�v�}�}�\�2��H�2<�V�]�]�:�.�"�F��%�%�h�(�C�C��%�%�f�h�?�?��A�h��b�	�t�+�E�!�H�d�1�g�>��+�E�!�H�d�1�g�>���&�&�{��J�J�#(��C��R��R��g�~��b��H�D���*�$�%���+�+��b��H�D���*�$�%��+�+��b��H�D���*�$�%�$)�B�s�AE'�E'�C!E'�"E'c��V^,pW,630pV'g631V^,pV^8:dRPV4#RPW"V,^,6324#r�r�r�s&&  r�_format_range_contextr�sO����	�I�
�\�F���Q��	�
��{��{�{�9�%�%��>�>�)��%7�!�%;�<�<rc	#�"�\WW#WEV4\RRRRR7pRp	\RW4PV4EF�p633V	'gaRp	V'dR	P	V4MR634pV'dR	P	V4MR635pRP	W+V4x�RP	W<V4x�V636^,V637R,r�R
V,x�\V
^,V^,4pRP	W�4x�\;QJdRV6384F'gKRM	RM
!RV63944'd7V640F0wppppVR8wgKVVVFpVV,V,x�K	K2	\V
^,V^,4pRP	VV4x�\;QJdRV6414F'gKRM	RM
!RV64244'gEK�V643F0wppppVR8wgKVVVFpVV,V,x�K	K2	EK�	R#5i)a�644Compare two sequences of lines; generate the delta as a context diff.645 646Context diffs are a compact way of showing line changes and a few647lines of context.  The number of context lines is set by 'n' which648defaults to three.649 650By default, the diff control lines (those with *** or ---) are651created with a trailing newline.  This is helpful so that inputs652created from file.readlines() result in diffs that are suitable for653file.writelines() since both the inputs and outputs have trailing654newlines.655 656For inputs that do not have trailing newlines, set the lineterm657argument to "" so that the output will be uniformly newline free.658 659The context diff format normally has a header for filenames and660modification times.  Any or all of these may be specified using661strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.662The modification times are normally expressed in the ISO 8601 format.663If not specified, the strings default to blanks.664 665Example:666 667>>> print(''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(True),668...       'zero\none\ntree\nfour\n'.splitlines(True), 'Original', 'Current')),669...       end="")670*** Original671--- Current672***************673*** 1,4 ****674  one675! two676! three677  four678--- 1,4 ----679+ zero680  one681! tree682  four683r�r�z! r�)rirhrgrjFNTrrfz684*** {}{}{}rz***************z
*** {} ****{}c3�6"�TFwpq!R9x�K	R#5i)rgN>rhrgr�rro�_s&  rr��context_diff.<locals>.<genexpr>�����I�5���Q��1�a�+�+�5���riz
--- {} ----{}c3�6"�TFwpq!R9x�K	R#5i)rgN>rirgrrs&  rr�r�rrrhru)r�dictrr{r�r�any)rrrrrrr9r�prefixrrzr	r685r�rrror\r`rr�r
r]ras&&&&&&&&                r�context_diffr�s����X��x��8�L�
��d�D��
E�F��G� ��a�*�>�>�q�A����G�6B�v�}�}�\�2��H�2<�V�]�]�:�.�"�F��%�%�h�(�C�C��%�%�f�h�?�?��A�h��b�	�t��(�*�*�+�E�!�H�d�1�g�>���$�$�[�;�;��3�I�5�I�3�3�3�I�5�I�I�I�%*�!��R��Q���(�?� !�"�R���$�S�k�D�0�0�!)�&+�686,�E�!�H�d�1�g�>���$�$�[�(�;�;��3�I�5�I�3�3�3�I�5�I�I�I�%*�!��Q��2�r��(�?� !�"�R���$�S�k�D�0�0�!)�&+�1B�s8�AH687�H688�.B H689�H690�,H691�A,H692�/H693�
H694�!)H695c��V'dS\V^,\4'g6\R\V^,4P:RV^,:R24hV'dS\V^,\4'g6\R\V^,4P:RV^,:R24h\V\4'd&\R\V4P,4h\V\4'd&\R\V4P,4hVF(p\V\4'dK\RV:24h	R#)rsz"lines to compare must be str, not � (�)z+input must be a sequence of strings, not %sz all arguments must be str, not: N)�696isinstance�str�	TypeError�typer�)rr�args�args&&* rrr�s��	��A�a�D�#�&�&���a��d��,�,�a��d�d�4�5�	5���A�a�D�#�&�&���a��d��,�,�a��d�d�4�5�	5��!�S����E��Q��(�(�)�*�	*��!�S����E��Q��(�(�)�*�	*����#�s�#�#��C�I�J�J�rc	697#�"�Rp	\\W�44p\\W�44pV	!V4pV	!V4pV	!V4pV	!V4pV	!V4pV!WW4WVWx4p698V699FpVPRR4x�K	R#5i)a�700Compare `a` and `b`, two sequences of lines represented as bytes rather701than str. This is a wrapper for `dfunc`, which is typically either702unified_diff() or context_diff(). Inputs are losslessly converted to703strings so that `dfunc` only has to worry about strings, and encoded704back to bytes on return. This is necessary to compare files with705unknown or inconsistent encoding. All other inputs (except `n`) must be706bytes rather than str.707c��VPRR4# \d0pR\T4P:RT:R2p\	T4ThRp?ii;i)�ascii�surrogateescapez!all arguments must be bytes, not rrN)�decode�AttributeErrorr#r�r")r��err�msgs&  rr*�diff_bytes.<locals>.decodesK��	*��8�8�G�%6�7�7���	*���G�$�$�a�)�C��C�.�c�)��	*�s��A�*A	�	Ar(r)N)rUrV�encode)�dfuncrrrrrrr9rr*�linesr�s&&&&&&&&&   r�708diff_bytesr2s����*�	
�S��^��A��S��^��A��h��H�
�F�^�F��,�'�L��709�#�J��h��H��!��,�A�P�E����k�k�'�#4�5�5��s�A>Bc�6�\W#4PW4#)a�710Compare `a` and `b` (lists of strings); return a `Differ`-style delta.711 712Optional keyword parameters `linejunk` and `charjunk` are for filter713functions, or can be None:714 715- linejunk: A function that should accept a single string argument and716  return true iff the string is junk.  The default is None, and is717  recommended; the underlying SequenceMatcher class has an adaptive718  notion of "noise" lines.719 720- charjunk: A function that accepts a character (string of length721  1), and returns true iff the character is junk. The default is722  the module-level function IS_CHARACTER_JUNK, which filters out723  whitespace characters (a blank or tab; note: it's a bad idea to724  include newline in this!).725 726Tools/scripts/ndiff.py is a command-line front-end to this function.727 728Example:729 730>>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True),731...              'ore\ntree\nemu\n'.splitlines(keepends=True))732>>> print(''.join(diff), end="")733- one734?  ^735+ ore736?  ^737- two738- three739?  -740+ tree741+ emu742)rr�)rrr�r�s&&&&r�ndiffr4s��F�(�%�-�-�a�3�3rc#�aaaa"�^RIpVPR4o\WW44o^^.3V3RlloVV3RloV3RlpV!4pVf
TRjx�L743R#V^,
p^p^R.V,r�RpVRJd)\V4wr�pY�,pY�T3Y�&T	^,
p	K.W�8�dRx�TpMT	p^p	V'd'W�,pV	^,
p	W�,x�V^,pK.V^,744pV'd2\V4wr�pV'dV^,745pM	V^,pW�V3x�K9K�L� \dR#i;i \dR#i;i5i)a{Returns generator yielding marked up from/to side by side differences.746 747Arguments:748fromlines -- list of text lines to compared to tolines749tolines -- list of text lines to be compared to fromlines750context -- number of context lines to display on each side of difference,751           if None, all from/to text lines will be generated.752linejunk -- passed on to ndiff (see ndiff documentation)753charjunk -- passed on to ndiff (see ndiff documentation)754 755This function returns an iterator which returns a tuple:756(from line tuple, to line tuple, boolean flag)757 758from/to line tuple -- (line num, line text)759    line num -- integer or None (to indicate a context separation)760    line text -- original line text with following markers inserted:761        '\0+' -- marks start of added text762        '\0-' -- marks start of deleted text763        '\0^' -- marks start of changed text764        '\1' -- marks end of added/deleted/changed text765 766boolean flag -- None indicates context separation, True indicates767    either "from" or "to" line contains a change, otherwise False.768 769This function/iterator was originally developed to generate side by side770file difference for making HTML pages (see HtmlDiff class for example771usage).772 773Note, this function utilizes the ndiff function to generate the side by774side difference markup.  Optional ndiff arguments may be passed to this775function and they in turn will be passed to ndiff.776Nz
(\++|\-+|\^+)c�<�W2;;,^,
uu&Vf!W2,VP^4R,3#VR8Xd�VP^4VP^4rT.pV3RlpSPWu4\V4F4wpwr�V^V	R,V,WIV777,R,WJR,pK6	VR,pM9VP^4R,pV'gRpRV,V,R,pW2,V3#)aReturns line of text with user's change markup and line formatting.778 779lines -- list of lines from the ndiff generator to produce a line of780         text from.  When producing the line of text to return, the781         lines used are removed from this list.782format_key -- '+' return first line in list with "add" markup around783                  the entire line.784              '-' return first line in list with "delete" markup around785                  the entire line.786              '?' return first line in list with add/delete/change787                  intraline markup (indices obtained from second line)788              None return first line in list with no markup789side -- indice into the num_lines list (0=from,1=to)790num_lines -- from/to current line number.  This is NOT intended to be a791             passed parameter.  It is present as a keyword argument to792             maintain memory of the current line numbers between calls793             of this function.794 795Note, this function is purposefully not defined at the module scope so796that data it needs from its parent function (within whose context it797is defined) does not need to be of module scope.798N��NN�?c��VPVP^4^,VP4.4VP^4#)rt)r,rz�span)�match_object�sub_infos&&r�record_sub_info�3_mdiff.<locals>._make_line.<locals>.record_sub_info�s=������!3�!3�A�!6�q�!9�,�:K�:K�:M� N�O�#�)�)�!�,�,r��r�)rS�sub�reversed)r1�799format_key�side�	num_lines�text�markersr=r>�key�begin�end�	change_res&&&&       �r�800_make_line�_mdiff.<locals>._make_linems����.	��1������O�E�I�I�a�L��$4�5�5����!�I�I�a�L�%�)�)�A�,�'��H�6>�
-�
�M�M�/�2�$,�H�#5���K�U��A�e�}�T�)�#�-�d��o�=�d�B�4��:�M��$6���8�D��9�9�Q�<��#�D�����*�$�t�+�d�2�D����%�%rc3�v<"�.p^^r!\V4^8dVP\SR44K-RPVUu.uFq3^,NK
	up4pVP	R4'dTpEM�VP	R4'dS!VR^4S!VR^4R3x�K�VP	R4'dV^,pS!VR^4RR3x�K�VP	R4'dS!VR^4RreV^,801^rEM]VP	R	4'dS!VR^4S!VR^4R3x�EK0VP	R8024'dS!VR^4S!VR^4R3x�EKaVP	R4'dV^,pS!VR^4RR3x�EK�VP	R4'dV^,
pRS!VR^4R3x�EK�VP	R4'dRS!VR^4reV^,^rMjVP	R4'dV^,
pRS!VR^4R3x�EK$VP	R
4'd"S!VR,R^4S!VR^4R3x�EK\V^8dV^,
pRx�KV^8�dV^,pRx�KVP	R4'dR#XXR3x�EK�uupi5i)aQYields from/to lines of text with a change indication.803 804This function is an iterator.  It itself pulls lines from a805differencing iterator, processes them and yields them.  When it can806it yields both a "from" and a "to" line, otherwise it will yield one807or the other.  In addition to yielding the lines of from/to text, a808boolean flag is yielded to indicate if the text line(s) have809differences in them.810 811Note, this function is purposefully not defined at the module scope so812that data it needs from its parent function (within whose context it813is defined) does not need to be of module scope.814T�Xrfz-?+?r9z--++r�Nz-+?z-?+z+--r�r�:NNNF)z--?+z--+r�)r�z+-)N�rfr�T)rQNT)r2r,�nextr��815startswith)	r1�num_blanks_pending�num_blanks_to_yieldr�r��	from_line�to_linerM�diff_lines_iterators	       ��r�_line_iterator�_mdiff.<locals>._line_iterator�s�������23�Q�/���e�*�q�.����T�"5�s�;�<����U�3�U�T�a���U�3�4�A��|�|�C� � �'9�#����f�%�%� ��s�1�-�z�%��A�/F��L�L�����f�%�%�#�a�'�"� ��s�1�-�t�T�9�9�����3�4�4�%/�u�S��$;�T�'�9K�A�9M�a�$6����e�$�$� ��t�A�.�816�5��Q�0G��M�M�����e�$�$� ��s�1�-�z�%��Q�/G��M�M�����c�"�"�"�a�'�"� ��s�1�-�t�T�9�9�����e�$�$�#�a�'�"��J�u�S��3�T�9�9�����l�+�+�%)�:�e�C��+B�7�9K�A�9M�a�$6����c�"�"�"�a�'�"��J�u�S��3�T�9�9�����c�"�"� ��q��$�q�1�*�U�4��2J�5�P�P��&��)�#�q�(�#�)�)�%��)�#�q�(�#�)�)��|�|�C� � �����,�,��A4�sQ�AJ9�J4�J9�5J9�/J9�AJ9�0J9�0J9�1J9�3AJ9�1J9�A#J9�(J9c3�t<"�S!4p..r!\V4^8Xg\V4^8Xd@\V4wr4pTeTPY534TfKKTPYE34K_VP	^4wr6VP	^4wrGY4T;'gT3x�K� \dR#i;i5i)a,Yields from/to lines of text with a change indication.817 818This function is an iterator.  It itself pulls lines from the line819iterator.  Its difference from that iterator is that this function820always yields a pair of from/to text lines (with the change821indication).  If necessary it will collect single from/to lines822until it has a matching pair from/to pair to yield.823 824Note, this function is purposefully not defined at the module scope so825that data it needs from its parent function (within whose context it826is defined) does not need to be of module scope.827N)r2rR�
StopIterationr,rS)	�
line_iterator�	fromlines�tolinesrVrW�828found_diff�fromDiff�to_diffrYs	        �r�_line_pair_iterator�#_mdiff.<locals>._line_pair_iterator�s�����'�(�
��R�'���y�>�1�$��G��a���59�-�5H�2�I�829��(��$�$�i�%;�<��&��N�N�G�#7�8�"+�-�-��"2��I�&�{�{�1�~��G��X�%8�%8��9�9��%����s.�,B8�B&�B8�AB8�&B5�1B8�4B5�5B8F)NNN)�re�compiler4rRr\)r^r_�contextr�r�rerc�line_pair_iterator�lines_to_write�index�contextLinesr`rVrWr4rYrMrLrXs&&&&&          @@@@r�_mdiffrlCsv����D��830�831�+�,�I� �	�(�D��78��e�6&�pV-�p:�B-�.����%�%�%�	�1������#$�d�V�W�%5�<��J���%��59�:L�5M�2�I�832��O��#,�z�"B�����833����&�&�!(��!&���� ��O����834��"�o�%��!�#��$�Q�Y�N�
�$�59�:L�5M�2�I�835�!�)0����&�!�+��#�j�8�8�%�I	&��%�����:!�
��
�sf�A836E�D"�%E�7D$�1E�7/E�'D6�/1D6� E�$D3�/E�2D3�3E�6E�E�E�Ean837<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"838          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">839 840<html>841 842<head>843    <meta http-equiv="Content-Type"844          content="text/html; charset=%(charset)s" />845    <title></title>846    <style type="text/css">%(styles)s847    </style>848</head>849 850<body>851    %(table)s%(legend)s852</body>853 854</html>a�855        :root {color-scheme: light dark}856        table.diff {font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; border:medium}857        .diff_header {background-color:#e0e0e0}858        td.diff_header {text-align:right}859        .diff_next {background-color:#c0c0c0}860        .diff_add {background-color:palegreen}861        .diff_chg {background-color:#ffff77}862        .diff_sub {background-color:#ffaaaa}863 864        @media (prefers-color-scheme: dark) {865            .diff_header {background-color:#666}866            .diff_next {background-color:#393939}867            .diff_add {background-color:darkgreen}868            .diff_chg {background-color:#847415}869            .diff_sub {background-color:darkred}870        }aZ871    <table class="diff" id="difflib_chg_%(prefix)s_top"872           cellspacing="0" cellpadding="0" rules="groups" >873        <colgroup></colgroup> <colgroup></colgroup> <colgroup></colgroup>874        <colgroup></colgroup> <colgroup></colgroup> <colgroup></colgroup>875        %(header_row)s876        <tbody>877%(data_rows)s        </tbody>878    </table>a�879    <table class="diff" summary="Legends">880        <tr> <th colspan="2"> Legends </th> </tr>881        <tr> <td> <table border="" summary="Colors">882                      <tr><th> Colors </th> </tr>883                      <tr><td class="diff_add">&nbsp;Added&nbsp;</td></tr>884                      <tr><td class="diff_chg">Changed</td> </tr>885                      <tr><td class="diff_sub">Deleted</td> </tr>886                  </table></td>887             <td> <table border="" summary="Links">888                      <tr><th colspan="2"> Links </th> </tr>889                      <tr><td>(f)irst change</td> </tr>890                      <tr><td>(n)ext change</td> </tr>891                      <tr><td>(t)op</td> </tr>892                  </table></td> </tr>893    </table>c�a�]tRtRtoRt]t]t]t]t^t	^RR]8943RltRRR/RlltRt
R	tR895tRtRtR
tRtRRltRtVtR#)ri�aWFor producing HTML side by side comparison with change highlights.896 897This class can be used to create an HTML table (or a complete HTML file898containing the table) showing a side by side, line by line comparison899of text with inter-line and intra-line change highlights.  The table can900be generated in either full or contextual difference mode.901 902The following methods are provided for HTML generation:903 904make_table -- generates HTML for a single side by side table905make_file -- generates complete HTML file with a single side by side table906 907See tools/scripts/diff.py for an example usage of this class.908Nc�6�WnW nW0nW@nR#)a�HtmlDiff instance initializer909 910Arguments:911tabsize -- tab stop spacing, defaults to 8.912wrapcolumn -- column number where lines are broken and wrapped,913    defaults to None where lines are not wrapped.914linejunk,charjunk -- keyword arguments passed into ndiff() (used by915    HtmlDiff() to generate the side by side HTML differences).  See916    ndiff() documentation for argument default values and descriptions.917N)�_tabsize�_wrapcolumn�	_linejunk�	_charjunk)r�tabsize�918wrapcolumnr�r�s&&&&&rr�HtmlDiff.__init__�s�� �
�%��!��!�r�charsetzutf-8c���VP\VPVPVP	WW4WVR7VR7,PVR4P
V4#)a�Returns HTML file of side by side comparison with change highlights919 920Arguments:921fromlines -- list of "from" lines922tolines -- list of "to" lines923fromdesc -- "from" file column header string924todesc -- "to" file column header string925context -- set to True for contextual differences (defaults to False926    which shows full differences).927numlines -- number of context lines.  When context is set True,928    controls number of lines displayed before and after the change.929    When context is False, controls the number of lines to place930    the "next" link anchors before the next change (so click of931    "next" link jumps to just before the change).932charset -- charset of the HTML document933)rg�numlines)�styles�legend�tablerv�xmlcharrefreplace)�_file_templater�_styles�_legend�934make_tabler/r*)rr^r_�fromdesc�todescrgrxrvs&&&&&&&$r�	make_file�HtmlDiff.make_file�s`��&�#�#�d��<�<��<�<��/�/�)�h�*1�"�F��'935�936��6�'�.�/���w��
	@rc�a�V3RlpVUu.uF937qC!V4NK	ppVUu.uF938qC!V4NK	ppW3#uupiuupi)a�Returns from/to line lists with tabs expanded and newlines removed.939 940Instead of tab characters being replaced by the number of spaces941needed to fill in to the next tab stop, this function will fill942the space with tab characters.  This is done so that the difference943algorithms can identify changes in a file when tabs are replaced by944spaces and vice versa.  At the end of the HTML generation, the tab945characters will be replaced with a nonbreakable space.946c��<�VPRR4pVPSP4pVPRR4pVPRR4PR4#)r�r@�	r�)rg�947expandtabsror�)r�rs&�r�expand_tabs�2HtmlDiff._tab_newline_replace.<locals>.expand_tabs�sS����<�<��D�)�D��?�?�4�=�=�1�D��<�<��D�)�D��<�<��S�)�0�0��6�6rr)rr^r_r�r�sf&&  r�_tab_newline_replace�HtmlDiff._tab_newline_replace�sM���	7�4=�=�9�4�[��&�9�	�=�18�9���;�t�$���9�� � ��>��9s�7�<c�V�V'gVPW#34R#\V4pVPpWE8:g$WCPR4^,,948V8:dVPW#34R#^p^pRpWu8d^Wd8dXW6,R8XdV^,
pW6,pV^,
pK5W6,R8XdV^,
pRpKOV^,
pV^,
pKcVRVp	W6Rp949V'dV	R,p	RV,V950,p951VPW)34VP	VRV9524R#)atBuilds list of text lines by splitting text lines at wrap point953 954This function will determine if the input text line needs to be955wrapped (split) into separate lines.  If so, the first wrap point956will be determined and the first line appended to the output957text line list.  This function is used recursively to handle958the second part of the split line to further split it.959Nr@rfrA�>)r,r2rp�count�_split_line)r�	data_list�line_numrGrnrvr4r9�mark�line1�line2s&&&&       rr��HtmlDiff._split_line�s������h�_�-���4�y�������K�d�Z�Z��%5�a�%7�8�S�@����h�_�-��
��
�����g�!�(��w�$���Q����w���Q�����D���Q������Q����Q����R�a����R���960��D�L�E��4�K�%�'�E�	���(�)�*�	
����3�u�-rc#�<"�VF�wr#pVf	W#V3x�KW#uwrVwrx..r�VPW�V4VPW�V4V	'gV961'gKSV	'dV	P^4pMRpV962'dV963P^4pMRpW#V3x�KR	R#5i)z5Returns iterator that splits (wraps) mdiff text linesN)rfr�)r�rS)r�diffs�fromdata�todata�flag�fromline�fromtext�toline�totext�fromlist�tolists&&         r�
_line_wrapper�HtmlDiff._line_wrapper"s����%*� �H�D��|��d�*�*��2:�/��X���!��V����X�x�8����V�6�2��f�f��'�|�|�A��H�'�H��#�Z�Z��]�F�%�F��d�*�*�-%*�s�AB�B�B� B�< Bc�F�...rCpVF`wrVpVPVP!^V.VO5!4VPVP!^V.VO5!4VPV4Kb	W#V3# \d&TPR4TPR4LHi;i)z�Collects mdiff output into separate lists964 965Before storing the mdiff from/to data into a list, it is converted966into a single line of text with HTML markup.967N)r,�_format_liner")rr�r�r��flaglistr�r�r�s&&      r�_collect_lines�HtmlDiff._collect_lines>s���$&�b����$)� �H�D�
$����� 1� 1�!�D� C�(� C�D��
�
�d�/�/��$�?��?�@�968
�O�O�D�!�%*��x�'�'���
$�����%��
�
�d�#�
$�s�AA0�0-B �B c�4�RV,pRVPV,:V:R2pVPRR4PRR4PR	R9694pVPRR4P4pR
V:RV:RV:R2# \dRpLpi;i)z�Returns HTML markup of "from" / "to" text lines970 971side -- 0 or 1 indicating "from" or "to" text972flag -- indicates if difference on line973linenum -- line number (used for line number column)974text -- line text to be marked up975z%dz id="�"rf�&z&amp;r�z&gt;�<z&lt;r��&nbsp;z<td class="diff_header"z</td><td nowrap="nowrap">z</td>)�_prefixr"rgr�)rrEr��linenumrG�ids&&&&& rr��HtmlDiff._format_lineSs���	��W�n�G�!%���d�!3�G�<�B�976�\�\�#�g�
&�
.�
.�s�6�
:�
B�
B�3�v�
N���|�|�C��)�0�0�2���W�T�#�	#���	��B�	�s�$B�
B�Bc��R\P,pR\P,p\;P^,
unW.VnR#)zCreate unique anchor prefixeszfrom%d_zto%d_N)r�_default_prefixr�)r�977fromprefix�toprefixs&  r�_make_prefix�HtmlDiff._make_prefixjs?��978��!9�!9�9�979��X�5�5�5��� � �A�%� �"�,��rc���VP^,pR.\V4,pR.\V4,p^Rr�^p\V4FSwr�V
'dEV980'g;Rp981Tp\^W�,982.4pRWi3,W|&V	^,
p	RWi3,W�&KOKQRp983KU	V'gR.pR.pR.p^pV'dR.pTpMR.;rV^,'g
RV,V^&R	V,W�&WW8V3#)984zMakes list of "next" linksrfFTz id="difflib_chg_%s_%d"z"<a href="#difflib_chg_%s_%d">n</a>z2<td></td><td>&nbsp;No Differences Found&nbsp;</td>z(<td></td><td>&nbsp;Empty File&nbsp;</td>z!<a href="#difflib_chg_%s_0">f</a>z#<a href="#difflib_chg_%s_top">t</a>)r�r2r*rv)rr�r�r�rgrxr��next_id�	next_href�num_chg�	in_changerr4r�s&&&&&&        r�_convert_flags�HtmlDiff._convert_flagsus���<�<��?���$�s�8�}�$���D��X��&�	��������)�F�A�� � $�I��D��Q�q�z�N�+�A�!:�h�=O�!O�G�J��q�L�G�&J�!�N+�'+�I�O�!�"�	�!*�$��w�H��d�G���I��D��P�Q��!��%O�$P�P����{�{�>��I�I�a�L�?�8�L�	���x�'�9�9rc985���VP4VPW4wrV'dTpMRp\WWpPVPR7pVP986'dVP
V4pVPV4wr�pVPW�W�V4wr�r�p
.pRp\\V44FipVV,fV^8�dVPR4K(K*VPW�V,VV,V	V,VV,V987V,3,4Kk	V'g	V'd RR:RV,:R:RV,:R2pMRpVP\RPV4VVP^,R	7,pVP!R988R4P!RR
4P!RR4P!RR4P!RR4#)a�Returns HTML table of side by side comparison with change highlights989 990Arguments:991fromlines -- list of "from" lines992tolines -- list of "to" lines993fromdesc -- "from" file column header string994todesc -- "to" file column header string995context -- set to True for contextual differences (defaults to False996    which shows full differences).997numlines -- number of context lines.  When context is set True,998    controls number of lines displayed before and after the change.999    When context is False, controls the number of lines to place1000    the "next" link anchors before the next change (so click of1001    "next" link jumps to just before the change).1002Nr�z)        </tbody>        1003        <tbody>1004z<thead><tr>z!<th class="diff_next"><br /></th>z+<th colspan="2" class="diff_header">%s</th>z
</tr></thead>rf)�	data_rows�1005header_rowrz+z<span class="diff_add">z-z<span class="diff_sub">z^z<span class="diff_chg">rAz</span>r�r�zV            <tr><td class="diff_next"%s>%s</td>%s<td class="diff_next">%s</td>%s</tr>1006)r�r�rlrqrrrpr�r�r�r@r2r,�_table_templaterr�r�rg)rr^r_r�r�rgrx�
context_linesr�r�r�r�r�r�r��fmtr4r�r{s&&&&&&&            rr��HtmlDiff.make_table�s���(	
����!�5�5�i�H��	��$�M� �M��y����#�~�~�/�������&�&�u�-�E�$(�#6�#6�u�#=� ���6:�5H�5H��H�X�67�2���7�
��7���s�8�}�%�A���{�"��q�5��H�H�J�K�����#���I�a�L��!��+4�Q�<��q�	�!C�C�D�&��v��3�=��H�3�=��F�F�	H�J��J��$�$�t��g�g�a�j�!��<�<��?�($�$��1007�}�}�U�#<�=��W�U�#<�=��W�U�#<�=��W�T�)�,��W�T�(�+�		,r)rrrqr�rorp)rfrfF�)r�r�r�r�r�r}r~r�rr�r�rr�r�r�r�r�r�r�r�r�r�r�r�s@rrr�st����
�$�N��G�%�O��G��O��4��+�"�"@�8?�@�6!�.5.�n+�8(�*#�.	-�-:�^K,�K,rc#��"�^R^R/\V4,pRT3pTFpTR,T9gKTR,x�K 	R# \d\RT,4Rhi;i5i)a�1008Generate one of the two sequences that generated a delta.1009 1010Given a `delta` produced by `Differ.compare()` or `ndiff()`, extract1011lines originating from file 1 or 2 (parameter `which`), stripping off line1012prefixes.1013 1014Examples:1015 1016>>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True),1017...              'ore\ntree\nemu\n'.splitlines(keepends=True))1018>>> diff = list(diff)1019>>> print(''.join(restore(diff, 1)), end="")1020one1021two1022three1023>>> print(''.join(restore(diff, 2)), end="")1024ore1025tree1026emu1027r�r�z)unknown delta choice (must be 1 or 2): %rNr�:Nr8Nr7)�int�KeyErrorr�)�delta�whichro�prefixesr�s&&   r�restorer��sv���,.��$��4� ��U��,���c�{�H�����8�x���r�(�N���	�.��D�"�#�$�)-�	.�.�s �A&�A�A&�A&�A#�#A&)r�r4r�rrr�r�rrr2rr)r�g333333�?)N)z 	)rfrfrfrfr�r�)rrrrr��1028)!r��__all__�heapqrr��collectionsr�_namedtuple�typesrrrrr�r�rr�r�r�rrrrr2r4rlr}r~r�r�objectrr�rrr�<module>r�s����8>��(�1���G�Z�(���1029k	2�k	2�\.&�b�j!�j!�z	!�*�.	-�B%�R	=�J1�XK�.6�<�(9�#4�J(,�d�%�K�\��(
��$����"],�v�],�@r
codekingpro/portable-devtools · Team Ai