diff mercurial/pure/parsers.py @ 52609:8de9bab826bc

pure: add an "abstractmethod" and some type hints to parsers.py to help pytype It looks like `BaseIndexObject` is meant to be a base class with common implementation across the subclasses. Both subclasses provide the class attrs typed here, as well as `_calculate_index()` that are accessed by the base class. The trick is, `revlog.RustIndexProxy` also uses it as a base class, and forwards some methods such that it doesn't want or need this method. This is kind of a workaround to keep everything happy. Likewise, it doesn't need the 3 class variables, because it overrides the methods in this class that use them. But there's no way to conditionally declare these. Their presence seems conditional on the version of Python- see 199b0e62b403. (Also, it looks like the rust class doesn't override `append()`, which would need `_extra`. Not sure if this is an oversight, or if it's more of a "protected" field instead of private.) `PersistentNodeMapIndexObject` says it's for debugging, so I'm not going to bother trying to figure out what the 3 required class attr types are right now, and risk introducing a cycle that confuses pytype.
author Matt Harbison <matt_harbison@yahoo.com>
date Mon, 16 Dec 2024 18:25:44 -0500
parents 7346f93be7a4
children 72af9fa34832
line wrap: on
line diff
--- a/mercurial/pure/parsers.py	Tue Dec 17 01:45:29 2024 -0500
+++ b/mercurial/pure/parsers.py	Mon Dec 16 18:25:44 2024 -0500
@@ -34,6 +34,12 @@
 from ..revlogutils import nodemap as nodemaputil
 from ..revlogutils import constants as revlog_constants
 
+if typing.TYPE_CHECKING:
+    from typing import (
+        Any,
+        ByteString,  # TODO: Change to Buffer for 3.14+ support
+    )
+
 stringio = io.BytesIO
 
 
@@ -600,6 +606,11 @@
         revlog_constants.RANK_UNKNOWN,
     )
 
+    # These aren't needed for rust
+    _data: ByteString
+    _extra: list[bytes]
+    _lgt: int
+
     @util.propertycache
     def entry_size(self):
         return self.index_format.size
@@ -657,6 +668,12 @@
         if i < 0 or i >= len(self):
             raise IndexError(i)
 
+    def _calculate_index(self, i: int) -> int:
+        # This isn't @abstractmethod because it is only used in __getitem__().
+        # The revlog.RustIndexProxy implementation provides its own, so there's
+        # no reason to force it to implement an unused method.
+        raise NotImplementedError
+
     def __getitem__(self, i):
         if i == -1:
             return self.null_item
@@ -729,7 +746,7 @@
         self._lgt = len(data) // self.entry_size
         self._extra = []
 
-    def _calculate_index(self, i):
+    def _calculate_index(self, i: int) -> int:
         return i * self.entry_size
 
     def __delitem__(self, i):
@@ -754,6 +771,11 @@
     through the dedicated `devel.persistent-nodemap` config.
     """
 
+    # TODO: add type info
+    _nm_docket: Any  # TODO: could be None, but need to handle .tip_rev below
+    _nm_max_idx: Any | None
+    _nm_root: Any | None
+
     def nodemap_data_all(self):
         """Return bytes containing a full serialization of a nodemap
 
@@ -829,7 +851,7 @@
         else:
             self._extra = self._extra[: i - self._lgt]
 
-    def _calculate_index(self, i):
+    def _calculate_index(self, i: int) -> int:
         return self._offsets[i]