Mercurial > public > mercurial-scm > hg
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 |
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 | 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 |