changeset 53247:aa95f9763fc3

typing: replace `typelib.CacheStat` with `ICacheStat` protocol class This takes out one (small) import cycle. There's an existing small import naming discrepancy- the `status` interface module is imported as `istatus`, and `misc` is imported as `int_misc`. I followed the latter here because copy/paste, before seeing `istatus` (which I prefer for less typing). (Plus 'int' makes me think number instead of 'interface'.)
author Matt Harbison <matt_harbison@yahoo.com>
date Wed, 30 Apr 2025 15:48:42 -0400
parents 578674e2b0df
children 16d650ea972f
files mercurial/dirstatemap.py mercurial/posix.py mercurial/scmutil.py mercurial/typelib.py mercurial/util.py mercurial/windows.py
diffstat 6 files changed, 26 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/dirstatemap.py	Wed Apr 30 15:31:30 2025 -0400
+++ b/mercurial/dirstatemap.py	Wed Apr 30 15:48:42 2025 -0400
@@ -14,7 +14,9 @@
 )
 
 from .i18n import _
-
+from .interfaces import (
+    misc as int_misc,
+)
 from . import (
     error,
     pathutil,
@@ -71,7 +73,7 @@
     _docket: Optional[docketmod.DirstateDocket]
     _write_mode: int
     _pendingmode: Optional[bool]
-    identity: Optional[typelib.CacheStat]
+    identity: Optional[int_misc.ICacheStat]
 
     # please pytype
 
@@ -110,7 +112,7 @@
         # for consistent view between _pl() and _read() invocations
         self._pendingmode = None
 
-    def _get_current_identity(self) -> Optional[typelib.CacheStat]:
+    def _get_current_identity(self) -> Optional[int_misc.ICacheStat]:
         # TODO have a cleaner approach on httpstaticrepo side
         path = self._opener.join(self._filename)
         if path.startswith(b'https://') or path.startswith(b'http://'):
@@ -173,7 +175,7 @@
     def _readdirstatefile(
         self,
         size: int = -1,
-    ) -> Tuple[Optional[typelib.CacheStat], bytes]:
+    ) -> Tuple[Optional[int_misc.ICacheStat], bytes]:
         """read the content of the file used as "entry point" for the dirstate
 
         Return a (identity, data) tuple. The identity can be used for cache
@@ -487,7 +489,7 @@
         self._dirtyparents = False
 
     @propertycache
-    def identity(self) -> Optional[typelib.CacheStat]:
+    def identity(self) -> Optional[int_misc.ICacheStat]:
         """A cache identifier for the state of the file as data were read
 
         This must always be set with the object returned from
--- a/mercurial/posix.py	Wed Apr 30 15:31:30 2025 -0400
+++ b/mercurial/posix.py	Wed Apr 30 15:48:42 2025 -0400
@@ -37,6 +37,7 @@
 )
 
 from .i18n import _
+from .interfaces import misc as int_misc
 from . import (
     encoding,
     error,
@@ -706,7 +707,7 @@
     pass
 
 
-class cachestat:
+class cachestat(int_misc.ICacheStat):
     stat: os.stat_result
 
     def __init__(self, path: bytes) -> None:
--- a/mercurial/scmutil.py	Wed Apr 30 15:31:30 2025 -0400
+++ b/mercurial/scmutil.py	Wed Apr 30 15:48:42 2025 -0400
@@ -64,7 +64,10 @@
     vfs,
 )
 
-from .interfaces import status as istatus
+from .interfaces import (
+    misc as int_misc,
+    status as istatus,
+)
 
 from .utils import (
     hashutil,
@@ -1764,7 +1767,7 @@
             return False
 
     @staticmethod
-    def stat(path: bytes) -> Optional[typelib.CacheStat]:
+    def stat(path: bytes) -> Optional[int_misc.ICacheStat]:
         # TODO have a cleaner approach on httpstaticrepo side
         if path.startswith(b'https://') or path.startswith(b'http://'):
             return util.uncacheable_cachestat()
--- a/mercurial/typelib.py	Wed Apr 30 15:31:30 2025 -0400
+++ b/mercurial/typelib.py	Wed Apr 30 15:48:42 2025 -0400
@@ -27,28 +27,18 @@
 if TYPE_CHECKING:
     from typing import (
         BinaryIO,
-        Union,
     )
 
     from . import (
         node,
-        posix,
-        util,
-        windows,
     )
 
     BinaryIO_Proxy = BinaryIO
-    CacheStat = Union[
-        posix.cachestat,
-        windows.cachestat,
-        util.uncacheable_cachestat,
-    ]
     NodeConstants = node.sha1nodeconstants
 else:
     from typing import Any
 
     BinaryIO_Proxy = object
-    CacheStat = Any
     NodeConstants = Any
 
 # scmutil.getuipathfn() related callback.
--- a/mercurial/util.py	Wed Apr 30 15:31:30 2025 -0400
+++ b/mercurial/util.py	Wed Apr 30 15:48:42 2025 -0400
@@ -526,7 +526,7 @@
         raise
 
 
-class uncacheable_cachestat:
+class uncacheable_cachestat(int_misc.ICacheStat):
     stat: Optional[os.stat_result]
 
     def __init__(self) -> None:
@@ -535,6 +535,14 @@
     def cacheable(self) -> bool:
         return False
 
+    __hash__ = object.__hash__
+
+    def __eq__(self, other: Any) -> bool:
+        return False
+
+    def __ne__(self, other: Any) -> bool:
+        return True
+
 
 class fileobjectproxy:
     """A proxy around file objects that tells a watcher when events occur.
--- a/mercurial/windows.py	Wed Apr 30 15:31:30 2025 -0400
+++ b/mercurial/windows.py	Wed Apr 30 15:48:42 2025 -0400
@@ -35,6 +35,8 @@
 )
 
 from .i18n import _
+from .interfaces import misc as int_misc
+
 from . import (
     encoding,
     error,
@@ -676,7 +678,7 @@
     return False
 
 
-class cachestat:
+class cachestat(int_misc.ICacheStat):
     stat: os.stat_result
 
     def __init__(self, path: bytes) -> None: