annotate mercurial/cffi/bdiff.py @ 51930:09f3a6790e56

interfaces: add the optional `bdiff.xdiffblocks()` method PyCharm flagged where this was called on the protocol class in `mdiff.py` in the previous commit, but pytype completely missed it. PyCharm is correct here, but I'm committing this separately to highlight this potential problem- some of the implementations don't implement _all_ of the methods the others do, and there's not a great way to indicate on a protocol class that a method or attribute is optional- that's kinda the opposite of what static typing is about. Making the method an `Optional[Callable]` attribute works here, and keeps both PyCharm and pytype happy, and the generated `mdiff.pyi` and `modules.pyi` look reasonable. We might be getting a little lucky, because the method isn't invoked directly- it is returned from another method that selects which block function to use. Except since it is declared on the protocol class, every module needs this attribute (in theory, but in practice this doesn't seem to be checked), so the check for it on the module has to change from `hasattr()` to `getattr(..., None)`. We defer defining the optional attrs to the type checking phase as an extra precaution- that way it isn't an attr with a `None` value at runtime if someone is still using `hasattr()`. As to why pytype missed this, I have no clue. The generated `mdiff.pyi` even has the global variable typed as `bdiff: intmod.BDiff`, so uses of it really should comply with what is on the class, protocol class or not.
author Matt Harbison <matt_harbison@yahoo.com>
date Sun, 29 Sep 2024 02:03:20 -0400
parents f4733654f144
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
32512
0e8b0b9a7acc cffi: split modules from pure
Yuya Nishihara <yuya@tcha.org>
parents: 32506
diff changeset
1 # bdiff.py - CFFI implementation of bdiff.c
7703
9044d3567f6d pure Python implementation of bdiff.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
2 #
32512
0e8b0b9a7acc cffi: split modules from pure
Yuya Nishihara <yuya@tcha.org>
parents: 32506
diff changeset
3 # Copyright 2016 Maciej Fijalkowski <fijall@gmail.com>
7703
9044d3567f6d pure Python implementation of bdiff.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
4 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7944
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 8225
diff changeset
6 # GNU General Public License version 2 or any later version.
7703
9044d3567f6d pure Python implementation of bdiff.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
7
51859
f4733654f144 typing: add `from __future__ import annotations` to most files
Matt Harbison <matt_harbison@yahoo.com>
parents: 51788
diff changeset
8 from __future__ import annotations
27335
c4e3ff497f89 bdiff: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 15530
diff changeset
9
c4e3ff497f89 bdiff: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 15530
diff changeset
10 import struct
51930
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
11 import typing
7944
e9b48afd0e78 pure/bdiff: fix circular import
Matt Mackall <mpm@selenic.com>
parents: 7703
diff changeset
12
49598
594fc56c0af7 typing: add type hints to bdiff implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 49597
diff changeset
13 from typing import (
594fc56c0af7 typing: add type hints to bdiff implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 49597
diff changeset
14 List,
51930
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
15 Optional,
49598
594fc56c0af7 typing: add type hints to bdiff implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 49597
diff changeset
16 Tuple,
594fc56c0af7 typing: add type hints to bdiff implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 49597
diff changeset
17 )
594fc56c0af7 typing: add type hints to bdiff implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 49597
diff changeset
18
32512
0e8b0b9a7acc cffi: split modules from pure
Yuya Nishihara <yuya@tcha.org>
parents: 32506
diff changeset
19 from ..pure.bdiff import *
51930
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
20
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
21 from ..interfaces import (
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
22 modules as intmod,
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
23 )
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
24
46785
521ac0d7047f typing: disable import error warnings that are already handled
Matt Harbison <matt_harbison@yahoo.com>
parents: 43077
diff changeset
25 from . import _bdiff # pytype: disable=import-error
7703
9044d3567f6d pure Python implementation of bdiff.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
26
32512
0e8b0b9a7acc cffi: split modules from pure
Yuya Nishihara <yuya@tcha.org>
parents: 32506
diff changeset
27 ffi = _bdiff.ffi
0e8b0b9a7acc cffi: split modules from pure
Yuya Nishihara <yuya@tcha.org>
parents: 32506
diff changeset
28 lib = _bdiff.lib
7703
9044d3567f6d pure Python implementation of bdiff.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
29
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 33572
diff changeset
30
49598
594fc56c0af7 typing: add type hints to bdiff implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 49597
diff changeset
31 def blocks(sa: bytes, sb: bytes) -> List[Tuple[int, int, int, int]]:
51786
ecc3a893979d cffi: pass C type and attribute names as str instead of bytes
Manuel Jacob <me@manueljacob.de>
parents: 49598
diff changeset
32 a = ffi.new("struct bdiff_line**")
ecc3a893979d cffi: pass C type and attribute names as str instead of bytes
Manuel Jacob <me@manueljacob.de>
parents: 49598
diff changeset
33 b = ffi.new("struct bdiff_line**")
51788
472699b5ddb3 cffi: pass bytes instead of str to ffi.new("char[]", ?)
Manuel Jacob <me@manueljacob.de>
parents: 51787
diff changeset
34 ac = ffi.new("char[]", bytes(sa))
472699b5ddb3 cffi: pass bytes instead of str to ffi.new("char[]", ?)
Manuel Jacob <me@manueljacob.de>
parents: 51787
diff changeset
35 bc = ffi.new("char[]", bytes(sb))
51786
ecc3a893979d cffi: pass C type and attribute names as str instead of bytes
Manuel Jacob <me@manueljacob.de>
parents: 49598
diff changeset
36 l = ffi.new("struct bdiff_hunk*")
32513
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
37 try:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
38 an = lib.bdiff_splitlines(ac, len(sa), a)
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
39 bn = lib.bdiff_splitlines(bc, len(sb), b)
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
40 if not a[0] or not b[0]:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
41 raise MemoryError
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
42 count = lib.bdiff_diff(a[0], an, b[0], bn, l)
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
43 if count < 0:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
44 raise MemoryError
49597
b2666e767029 cffi: adjust the list returned by bdiff.blocks to never have a None entry
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
45 rl = [(0, 0, 0, 0)] * count
32513
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
46 h = l.next
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
47 i = 0
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
48 while h:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
49 rl[i] = (h.a1, h.a2, h.b1, h.b2)
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
50 h = h.next
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
51 i += 1
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
52 finally:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
53 lib.free(a[0])
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
54 lib.free(b[0])
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
55 lib.bdiff_freehunks(l.next)
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
56 return rl
29834
1ea77b75d266 bdiff: implement cffi version of bdiff
Maciej Fijalkowski <fijall@gmail.com>
parents: 29833
diff changeset
57
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 33572
diff changeset
58
49598
594fc56c0af7 typing: add type hints to bdiff implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 49597
diff changeset
59 def bdiff(sa: bytes, sb: bytes) -> bytes:
51786
ecc3a893979d cffi: pass C type and attribute names as str instead of bytes
Manuel Jacob <me@manueljacob.de>
parents: 49598
diff changeset
60 a = ffi.new("struct bdiff_line**")
ecc3a893979d cffi: pass C type and attribute names as str instead of bytes
Manuel Jacob <me@manueljacob.de>
parents: 49598
diff changeset
61 b = ffi.new("struct bdiff_line**")
51788
472699b5ddb3 cffi: pass bytes instead of str to ffi.new("char[]", ?)
Manuel Jacob <me@manueljacob.de>
parents: 51787
diff changeset
62 ac = ffi.new("char[]", bytes(sa))
472699b5ddb3 cffi: pass bytes instead of str to ffi.new("char[]", ?)
Manuel Jacob <me@manueljacob.de>
parents: 51787
diff changeset
63 bc = ffi.new("char[]", bytes(sb))
51786
ecc3a893979d cffi: pass C type and attribute names as str instead of bytes
Manuel Jacob <me@manueljacob.de>
parents: 49598
diff changeset
64 l = ffi.new("struct bdiff_hunk*")
32513
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
65 try:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
66 an = lib.bdiff_splitlines(ac, len(sa), a)
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
67 bn = lib.bdiff_splitlines(bc, len(sb), b)
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
68 if not a[0] or not b[0]:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
69 raise MemoryError
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
70 count = lib.bdiff_diff(a[0], an, b[0], bn, l)
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
71 if count < 0:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
72 raise MemoryError
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
73 rl = []
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
74 h = l.next
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
75 la = lb = 0
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
76 while h:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
77 if h.a1 != la or h.b1 != lb:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
78 lgt = (b[0] + h.b1).l - (b[0] + lb).l
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 33572
diff changeset
79 rl.append(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 33572
diff changeset
80 struct.pack(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
81 b">lll",
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 33572
diff changeset
82 (a[0] + la).l - a[0].l,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 33572
diff changeset
83 (a[0] + h.a1).l - a[0].l,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 33572
diff changeset
84 lgt,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 33572
diff changeset
85 )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 33572
diff changeset
86 )
51787
6d7fdf90aa96 cffi: call bytes() instead of str() on CFFI buffer instances
Manuel Jacob <me@manueljacob.de>
parents: 51786
diff changeset
87 rl.append(bytes(ffi.buffer((b[0] + lb).l, lgt)))
32513
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
88 la = h.a2
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
89 lb = h.b2
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
90 h = h.next
29834
1ea77b75d266 bdiff: implement cffi version of bdiff
Maciej Fijalkowski <fijall@gmail.com>
parents: 29833
diff changeset
91
32513
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
92 finally:
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
93 lib.free(a[0])
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
94 lib.free(b[0])
25b37900d6e0 cffi: remove superfluous "if True" blocks
Yuya Nishihara <yuya@tcha.org>
parents: 32512
diff changeset
95 lib.bdiff_freehunks(l.next)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
96 return b"".join(rl)
51930
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
97
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
98
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
99 # In order to adhere to the module protocol, these functions must be visible to
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
100 # the type checker, though they aren't actually implemented by this
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
101 # implementation of the module protocol. Callers are responsible for
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
102 # checking that the implementation is available before using them.
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
103 if typing.TYPE_CHECKING:
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
104 xdiffblocks: Optional[intmod.BDiffBlocksFnc] = None