Show More
@@ -9,8 +9,20 from __future__ import annotations | |||
|
9 | 9 | |
|
10 | 10 | import re |
|
11 | 11 | import struct |
|
12 | import typing | |
|
12 | 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 | 26 | from .i18n import _ |
|
15 | 27 | from . import ( |
|
16 | 28 | diffhelper, |
@@ -36,6 +48,21 patchedsize = mpatch.patchedsize | |||
|
36 | 48 | textdiff = bdiff.bdiff |
|
37 | 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 | 67 | # TODO: this looks like it could be an attrs, which might help pytype |
|
41 | 68 | class diffopts: |
@@ -107,7 +134,7 class diffopts: | |||
|
107 | 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 | 138 | if opts.ignorews: |
|
112 | 139 | text = bdiff.fixws(text, True) |
|
113 | 140 | elif opts.ignorewsamount: |
@@ -119,7 +146,13 def wsclean(opts, text, blank=True): | |||
|
119 | 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 | 156 | # The input lines matches except for interwoven blank lines. We |
|
124 | 157 | # transform it into a sequence of matching blocks and blank blocks. |
|
125 | 158 | lines1 = [(wsclean(opts, l) and 1 or 0) for l in lines1] |
@@ -145,7 +178,7 def splitblock(base1, lines1, base2, lin | |||
|
145 | 178 | s2 = i2 |
|
146 | 179 | |
|
147 | 180 | |
|
148 | def hunkinrange(hunk, linerange): | |
|
181 | def hunkinrange(hunk: Tuple[int, int], linerange: Range) -> bool: | |
|
149 | 182 | """Return True if `hunk` defined as (start, length) is in `linerange` |
|
150 | 183 | defined as (lowerbound, upperbound). |
|
151 | 184 | |
@@ -171,7 +204,9 def hunkinrange(hunk, linerange): | |||
|
171 | 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 | 210 | """filter `blocks` like (a1, a2, b1, b2) from items outside line range |
|
176 | 211 | `rangeb` from ``(b1, b2)`` point of view. |
|
177 | 212 | |
@@ -211,7 +246,7 def blocksinrange(blocks, rangeb): | |||
|
211 | 246 | return filteredblocks, (lba, uba) |
|
212 | 247 | |
|
213 | 248 | |
|
214 | def chooseblocksfunc(opts=None): | |
|
249 | def chooseblocksfunc(opts: Optional[diffopts] = None) -> intmod.BDiffBlocksFnc: | |
|
215 | 250 | if ( |
|
216 | 251 | opts is None |
|
217 | 252 | or not opts.xdiff |
@@ -222,7 +257,13 def chooseblocksfunc(opts=None): | |||
|
222 | 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 | 267 | """Return (block, type) tuples, where block is an mdiff.blocks |
|
227 | 268 | line entry. type is '=' for blocks matching exactly one another |
|
228 | 269 | (bdiff blocks), '!' for non-matching blocks and '~' for blocks |
@@ -264,7 +305,16 def allblocks(text1, text2, opts=None, l | |||
|
264 | 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 | 318 | """Return a unified diff as a (headers, hunks) tuple. |
|
269 | 319 | |
|
270 | 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 | 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 | 329 | if not opts.git and not opts.nodates: |
|
280 | 330 | return b'\t%s' % date |
|
281 | 331 | if fn and b' ' in fn: |
@@ -344,10 +394,16 def unidiff(a, ad, b, bd, fn1, fn2, bina | |||
|
344 | 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 | 407 | """Yield hunks of a headerless unified diff from t1 and t2 texts. |
|
352 | 408 | |
|
353 | 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 | 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 | 437 | (astart, a2, bstart, b2, delta) = hunk |
|
380 | 438 | aend = contextend(a2, len(l1)) |
|
381 | 439 | alen = aend - astart |
@@ -495,7 +553,7 def _unidiff(t1, t2, opts=defaultopts): | |||
|
495 | 553 | yield False |
|
496 | 554 | |
|
497 | 555 | |
|
498 | def b85diff(to, tn): | |
|
556 | def b85diff(to: Optional[bytes], tn: Optional[bytes]) -> bytes: | |
|
499 | 557 | '''print base85-encoded binary diff''' |
|
500 | 558 | |
|
501 | 559 | def fmtline(line): |
@@ -532,7 +590,7 def b85diff(to, tn): | |||
|
532 | 590 | return b''.join(ret) |
|
533 | 591 | |
|
534 | 592 | |
|
535 | def patchtext(bin): | |
|
593 | def patchtext(bin: bytes) -> bytes: | |
|
536 | 594 | pos = 0 |
|
537 | 595 | t = [] |
|
538 | 596 | while pos < len(bin): |
@@ -551,13 +609,13 def patch(a, bin): | |||
|
551 | 609 | |
|
552 | 610 | |
|
553 | 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 | 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 | 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 | 621 | return struct.pack(b">lll", 0, oldlen, newlen) |
General Comments 0
You need to be logged in to leave comments.
Login now