annotate mercurial/interfaces/modules.py @ 51934: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 f2832de2a46c
children fa7059f031a9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
51933
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
1 # modules.py - protocol classes for dynamically loaded modules
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
2 #
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
3 # This software may be used and distributed according to the terms of the
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
4 # GNU General Public License version 2 or any later version.
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
5
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
6 from __future__ import annotations
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
7
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
8 import typing
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
9
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
10 from typing import (
51934
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51933
diff changeset
11 Callable,
51933
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
12 List,
51934
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51933
diff changeset
13 Optional,
51933
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
14 Protocol,
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
15 Tuple,
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
16 )
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
17
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
18 if typing.TYPE_CHECKING:
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
19 BDiffBlock = Tuple[int, int, int, int]
51934
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51933
diff changeset
20 """An entry in the list returned by bdiff.{xdiff,}blocks()."""
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51933
diff changeset
21
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51933
diff changeset
22 BDiffBlocksFnc = Callable[[bytes, bytes], List[BDiffBlock]]
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51933
diff changeset
23 """The signature of `bdiff.blocks()` and `bdiff.xdiffblocks()`."""
51933
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
24
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
25
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
26 class BDiff(Protocol):
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
27 """A Protocol class for the various bdiff module implementations."""
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
28
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
29 def splitnewlines(self, text: bytes) -> List[bytes]:
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
30 """like str.splitlines, but only split on newlines."""
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
31
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
32 def bdiff(self, a: bytes, b: bytes) -> bytes:
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
33 ...
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
34
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
35 def blocks(self, a: bytes, b: bytes) -> List[BDiffBlock]:
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
36 ...
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
37
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
38 def fixws(self, text: bytes, allws: bool) -> bytes:
f2832de2a46c interfaces: introduce and use a protocol class for the `bdiff` module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
39 ...
51934
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51933
diff changeset
40
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51933
diff changeset
41 xdiffblocks: Optional[BDiffBlocksFnc]
09f3a6790e56 interfaces: add the optional `bdiff.xdiffblocks()` method
Matt Harbison <matt_harbison@yahoo.com>
parents: 51933
diff changeset
42 """This method is currently only available in the ``cext`` module."""