##// END OF EJS Templates
typing: add type annotations to `mercurial/mdiff.py`...
Matt Harbison -
r52829:c6899b33 default
parent child Browse files
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(blocks, rangeb):
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(hunk):
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