Show More
@@ -9,8 +9,20 from __future__ import annotations | |||||
9 |
|
9 | |||
10 | import re |
|
10 | import re | |
11 | import struct |
|
11 | import struct | |
|
12 | import typing | |||
12 | import zlib |
|
13 | import zlib | |
13 |
|
14 | |||
|
15 | from typing import ( | |||
|
16 | Iterable, | |||
|
17 | Iterator, | |||
|
18 | List, | |||
|
19 | Optional, | |||
|
20 | Sequence, | |||
|
21 | Tuple, | |||
|
22 | Union, | |||
|
23 | cast, | |||
|
24 | ) | |||
|
25 | ||||
14 | from .i18n import _ |
|
26 | from .i18n import _ | |
15 | from . import ( |
|
27 | from . import ( | |
16 | diffhelper, |
|
28 | diffhelper, | |
@@ -36,6 +48,21 patchedsize = mpatch.patchedsize | |||||
36 | textdiff = bdiff.bdiff |
|
48 | textdiff = bdiff.bdiff | |
37 | splitnewlines = bdiff.splitnewlines |
|
49 | splitnewlines = bdiff.splitnewlines | |
38 |
|
50 | |||
|
51 | if typing.TYPE_CHECKING: | |||
|
52 | HunkLines = List[bytes] | |||
|
53 | """Lines of a hunk- a header, followed by line additions and deletions.""" | |||
|
54 | ||||
|
55 | HunkRange = Tuple[int, int, int, int] | |||
|
56 | """HunkRange represents the range information of a hunk. | |||
|
57 | ||||
|
58 | The tuple (s1, l1, s2, l2) forms the header '@@ -s1,l1 +s2,l2 @@'.""" | |||
|
59 | ||||
|
60 | Range = Tuple[int, int] | |||
|
61 | """A (lowerbound, upperbound) range tuple.""" | |||
|
62 | ||||
|
63 | TypedBlock = Tuple[intmod.BDiffBlock, bytes] | |||
|
64 | """A bdiff block with its type.""" | |||
|
65 | ||||
39 |
|
66 | |||
40 | # TODO: this looks like it could be an attrs, which might help pytype |
|
67 | # TODO: this looks like it could be an attrs, which might help pytype | |
41 | class diffopts: |
|
68 | class diffopts: | |
@@ -107,7 +134,7 class diffopts: | |||||
107 | defaultopts = diffopts() |
|
134 | defaultopts = diffopts() | |
108 |
|
135 | |||
109 |
|
136 | |||
110 | def wsclean(opts, text, blank=True): |
|
137 | def wsclean(opts: diffopts, text: bytes, blank: bool = True) -> bytes: | |
111 | if opts.ignorews: |
|
138 | if opts.ignorews: | |
112 | text = bdiff.fixws(text, True) |
|
139 | text = bdiff.fixws(text, True) | |
113 | elif opts.ignorewsamount: |
|
140 | elif opts.ignorewsamount: | |
@@ -119,7 +146,13 def wsclean(opts, text, blank=True): | |||||
119 | return text |
|
146 | return text | |
120 |
|
147 | |||
121 |
|
148 | |||
122 | def splitblock(base1, lines1, base2, lines2, opts): |
|
149 | def splitblock( | |
|
150 | base1: int, | |||
|
151 | lines1: Iterable[bytes], | |||
|
152 | base2: int, | |||
|
153 | lines2: Iterable[bytes], | |||
|
154 | opts: diffopts, | |||
|
155 | ) -> Iterable[TypedBlock]: | |||
123 | # The input lines matches except for interwoven blank lines. We |
|
156 | # The input lines matches except for interwoven blank lines. We | |
124 | # transform it into a sequence of matching blocks and blank blocks. |
|
157 | # transform it into a sequence of matching blocks and blank blocks. | |
125 | lines1 = [(wsclean(opts, l) and 1 or 0) for l in lines1] |
|
158 | lines1 = [(wsclean(opts, l) and 1 or 0) for l in lines1] | |
@@ -145,7 +178,7 def splitblock(base1, lines1, base2, lin | |||||
145 | s2 = i2 |
|
178 | s2 = i2 | |
146 |
|
179 | |||
147 |
|
180 | |||
148 | def hunkinrange(hunk, linerange): |
|
181 | def hunkinrange(hunk: Tuple[int, int], linerange: Range) -> bool: | |
149 | """Return True if `hunk` defined as (start, length) is in `linerange` |
|
182 | """Return True if `hunk` defined as (start, length) is in `linerange` | |
150 | defined as (lowerbound, upperbound). |
|
183 | defined as (lowerbound, upperbound). | |
151 |
|
184 | |||
@@ -171,7 +204,9 def hunkinrange(hunk, linerange): | |||||
171 | return lowerbound < start + length and start < upperbound |
|
204 | return lowerbound < start + length and start < upperbound | |
172 |
|
205 | |||
173 |
|
206 | |||
174 |
def blocksinrange( |
|
207 | def blocksinrange( | |
|
208 | blocks: Iterable[TypedBlock], rangeb: Range | |||
|
209 | ) -> Tuple[List[TypedBlock], Range]: | |||
175 | """filter `blocks` like (a1, a2, b1, b2) from items outside line range |
|
210 | """filter `blocks` like (a1, a2, b1, b2) from items outside line range | |
176 | `rangeb` from ``(b1, b2)`` point of view. |
|
211 | `rangeb` from ``(b1, b2)`` point of view. | |
177 |
|
212 | |||
@@ -211,7 +246,7 def blocksinrange(blocks, rangeb): | |||||
211 | return filteredblocks, (lba, uba) |
|
246 | return filteredblocks, (lba, uba) | |
212 |
|
247 | |||
213 |
|
248 | |||
214 | def chooseblocksfunc(opts=None): |
|
249 | def chooseblocksfunc(opts: Optional[diffopts] = None) -> intmod.BDiffBlocksFnc: | |
215 | if ( |
|
250 | if ( | |
216 | opts is None |
|
251 | opts is None | |
217 | or not opts.xdiff |
|
252 | or not opts.xdiff | |
@@ -222,7 +257,13 def chooseblocksfunc(opts=None): | |||||
222 | return bdiff.xdiffblocks |
|
257 | return bdiff.xdiffblocks | |
223 |
|
258 | |||
224 |
|
259 | |||
225 | def allblocks(text1, text2, opts=None, lines1=None, lines2=None): |
|
260 | def allblocks( | |
|
261 | text1: bytes, | |||
|
262 | text2: bytes, | |||
|
263 | opts: Optional[diffopts] = None, | |||
|
264 | lines1: Optional[Sequence[bytes]] = None, | |||
|
265 | lines2: Optional[Sequence[bytes]] = None, | |||
|
266 | ) -> Iterable[TypedBlock]: | |||
226 | """Return (block, type) tuples, where block is an mdiff.blocks |
|
267 | """Return (block, type) tuples, where block is an mdiff.blocks | |
227 | line entry. type is '=' for blocks matching exactly one another |
|
268 | line entry. type is '=' for blocks matching exactly one another | |
228 | (bdiff blocks), '!' for non-matching blocks and '~' for blocks |
|
269 | (bdiff blocks), '!' for non-matching blocks and '~' for blocks | |
@@ -264,7 +305,16 def allblocks(text1, text2, opts=None, l | |||||
264 | yield s1, b'=' |
|
305 | yield s1, b'=' | |
265 |
|
306 | |||
266 |
|
307 | |||
267 | def unidiff(a, ad, b, bd, fn1, fn2, binary, opts=defaultopts): |
|
308 | def unidiff( | |
|
309 | a: bytes, | |||
|
310 | ad: bytes, | |||
|
311 | b: bytes, | |||
|
312 | bd: bytes, | |||
|
313 | fn1: bytes, | |||
|
314 | fn2: bytes, | |||
|
315 | binary: bool, | |||
|
316 | opts: diffopts = defaultopts, | |||
|
317 | ) -> Tuple[List[bytes], Iterable[Tuple[Optional[HunkRange], HunkLines]]]: | |||
268 | """Return a unified diff as a (headers, hunks) tuple. |
|
318 | """Return a unified diff as a (headers, hunks) tuple. | |
269 |
|
319 | |||
270 | If the diff is not null, `headers` is a list with unified diff header |
|
320 | If the diff is not null, `headers` is a list with unified diff header | |
@@ -275,7 +325,7 def unidiff(a, ad, b, bd, fn1, fn2, bina | |||||
275 | Set binary=True if either a or b should be taken as a binary file. |
|
325 | Set binary=True if either a or b should be taken as a binary file. | |
276 | """ |
|
326 | """ | |
277 |
|
327 | |||
278 | def datetag(date, fn=None): |
|
328 | def datetag(date: bytes, fn: Optional[bytes] = None): | |
279 | if not opts.git and not opts.nodates: |
|
329 | if not opts.git and not opts.nodates: | |
280 | return b'\t%s' % date |
|
330 | return b'\t%s' % date | |
281 | if fn and b' ' in fn: |
|
331 | if fn and b' ' in fn: | |
@@ -344,10 +394,16 def unidiff(a, ad, b, bd, fn1, fn2, bina | |||||
344 | b"+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2)), |
|
394 | b"+++ %s%s%s" % (bprefix, fn2, datetag(bd, fn2)), | |
345 | ] |
|
395 | ] | |
346 |
|
396 | |||
347 | return headerlines, hunks |
|
397 | # The possible bool is consumed from the iterator above in the `next()` | |
|
398 | # call. | |||
|
399 | return headerlines, cast( | |||
|
400 | "Iterable[Tuple[Optional[HunkRange], HunkLines]]", hunks | |||
|
401 | ) | |||
348 |
|
402 | |||
349 |
|
403 | |||
350 | def _unidiff(t1, t2, opts=defaultopts): |
|
404 | def _unidiff( | |
|
405 | t1: bytes, t2: bytes, opts: diffopts = defaultopts | |||
|
406 | ) -> Iterator[Union[bool, Tuple[HunkRange, HunkLines]]]: | |||
351 | """Yield hunks of a headerless unified diff from t1 and t2 texts. |
|
407 | """Yield hunks of a headerless unified diff from t1 and t2 texts. | |
352 |
|
408 | |||
353 | Each hunk consists of a (hunkrange, hunklines) tuple where `hunkrange` is a |
|
409 | Each hunk consists of a (hunkrange, hunklines) tuple where `hunkrange` is a | |
@@ -375,7 +431,9 def _unidiff(t1, t2, opts=defaultopts): | |||||
375 |
|
431 | |||
376 | lastfunc = [0, b''] |
|
432 | lastfunc = [0, b''] | |
377 |
|
433 | |||
378 |
def yieldhunk( |
|
434 | def yieldhunk( | |
|
435 | hunk: Tuple[int, int, int, int, List[bytes]] | |||
|
436 | ) -> Iterable[Tuple[HunkRange, HunkLines]]: | |||
379 | (astart, a2, bstart, b2, delta) = hunk |
|
437 | (astart, a2, bstart, b2, delta) = hunk | |
380 | aend = contextend(a2, len(l1)) |
|
438 | aend = contextend(a2, len(l1)) | |
381 | alen = aend - astart |
|
439 | alen = aend - astart | |
@@ -495,7 +553,7 def _unidiff(t1, t2, opts=defaultopts): | |||||
495 | yield False |
|
553 | yield False | |
496 |
|
554 | |||
497 |
|
555 | |||
498 | def b85diff(to, tn): |
|
556 | def b85diff(to: Optional[bytes], tn: Optional[bytes]) -> bytes: | |
499 | '''print base85-encoded binary diff''' |
|
557 | '''print base85-encoded binary diff''' | |
500 |
|
558 | |||
501 | def fmtline(line): |
|
559 | def fmtline(line): | |
@@ -532,7 +590,7 def b85diff(to, tn): | |||||
532 | return b''.join(ret) |
|
590 | return b''.join(ret) | |
533 |
|
591 | |||
534 |
|
592 | |||
535 | def patchtext(bin): |
|
593 | def patchtext(bin: bytes) -> bytes: | |
536 | pos = 0 |
|
594 | pos = 0 | |
537 | t = [] |
|
595 | t = [] | |
538 | while pos < len(bin): |
|
596 | while pos < len(bin): | |
@@ -551,13 +609,13 def patch(a, bin): | |||||
551 |
|
609 | |||
552 |
|
610 | |||
553 | # similar to difflib.SequenceMatcher.get_matching_blocks |
|
611 | # similar to difflib.SequenceMatcher.get_matching_blocks | |
554 | def get_matching_blocks(a, b): |
|
612 | def get_matching_blocks(a: bytes, b: bytes) -> List[Tuple[int, int, int]]: | |
555 | return [(d[0], d[2], d[1] - d[0]) for d in bdiff.blocks(a, b)] |
|
613 | return [(d[0], d[2], d[1] - d[0]) for d in bdiff.blocks(a, b)] | |
556 |
|
614 | |||
557 |
|
615 | |||
558 | def trivialdiffheader(length): |
|
616 | def trivialdiffheader(length: int) -> bytes: | |
559 | return struct.pack(b">lll", 0, 0, length) if length else b'' |
|
617 | return struct.pack(b">lll", 0, 0, length) if length else b'' | |
560 |
|
618 | |||
561 |
|
619 | |||
562 | def replacediffheader(oldlen, newlen): |
|
620 | def replacediffheader(oldlen: int, newlen: int) -> bytes: | |
563 | return struct.pack(b">lll", 0, oldlen, newlen) |
|
621 | return struct.pack(b">lll", 0, oldlen, newlen) |
General Comments 0
You need to be logged in to leave comments.
Login now