changeset 52753:ae2848198462

typing: add annotation to the public API of the transaction This prepare official protocol for the transaction (itself motivated by breaking the import cycle that slow pytype run to a crawl).
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Fri, 07 Feb 2025 16:40:49 +0100
parents 4eede65d68cf
children a7dcb7c1ff5a
files mercurial/interfaces/_basetypes.py mercurial/interfaces/types.py mercurial/transaction.py
diffstat 3 files changed, 84 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/interfaces/_basetypes.py	Thu Feb 06 20:43:34 2025 -0500
+++ b/mercurial/interfaces/_basetypes.py	Fri Feb 07 16:40:49 2025 +0100
@@ -21,3 +21,9 @@
 
 FsPathT = bytes
 """A path on disk (after vfs encoding)."""
+
+VfsKeyT = bytes
+"""Vfs identifier, typically used in a VfsMap."""
+
+CallbackCategoryT = bytes
+"""Key identifying a callback category."""
--- a/mercurial/interfaces/types.py	Thu Feb 06 20:43:34 2025 -0500
+++ b/mercurial/interfaces/types.py	Fri Feb 07 16:40:49 2025 +0100
@@ -12,9 +12,11 @@
 from __future__ import annotations
 
 from ._basetypes import (  # noqa: F401 (ignore imported but not used)
+    CallbackCategoryT,
     FsPathT,
     HgPathT,
     UserMsgT,
+    VfsKeyT,
 )
 
 from . import (
--- a/mercurial/transaction.py	Thu Feb 06 20:43:34 2025 -0500
+++ b/mercurial/transaction.py	Fri Feb 07 16:40:49 2025 +0100
@@ -16,7 +16,21 @@
 import errno
 import os
 
+from typing import (
+    Callable,
+    Collection,
+    List,
+    Optional,
+    Tuple,
+    Union,
+)
+
 from .i18n import _
+from .interfaces.types import (
+    CallbackCategoryT,
+    HgPathT,
+    VfsKeyT,
+)
 from . import (
     encoding,
     error,
@@ -31,6 +45,8 @@
 GEN_GROUP_PRE_FINALIZE = b'prefinalize'
 GEN_GROUP_POST_FINALIZE = b'postfinalize'
 
+JournalEntryT = Tuple[HgPathT, int]
+
 
 def active(func):
     def _active(self, *args, **kwds):
@@ -336,11 +352,11 @@
             self._abort()
 
     @property
-    def finalized(self):
+    def finalized(self) -> bool:
         return self._finalizecallback is None
 
     @active
-    def startgroup(self):
+    def startgroup(self) -> None:
         """delay registration of file entry
 
         This is used by strip to delay vision of strip offset. The transaction
@@ -348,7 +364,7 @@
         self._queue.append([])
 
     @active
-    def endgroup(self):
+    def endgroup(self) -> None:
         """apply delayed registration of file entry.
 
         This is used by strip to delay vision of strip offset. The transaction
@@ -358,7 +374,7 @@
             self._addentry(f, o)
 
     @active
-    def add(self, file, offset):
+    def add(self, file: HgPathT, offset: int) -> None:
         """record the state of an append-only file before update"""
         if (
             file in self._newfiles
@@ -391,7 +407,13 @@
         self._file.flush()
 
     @active
-    def addbackup(self, file, hardlink=True, location=b'', for_offset=False):
+    def addbackup(
+        self,
+        file: HgPathT,
+        hardlink: bool = True,
+        location: VfsKeyT = b'',
+        for_offset: Union[bool, int] = False,
+    ) -> None:
         """Adds a backup of the file to the transaction
 
         Calling addbackup() creates a hardlink backup of the specified file
@@ -445,7 +467,7 @@
         self._backupsfile.flush()
 
     @active
-    def registertmp(self, tmpfile, location=b''):
+    def registertmp(self, tmpfile: HgPathT, location: VfsKeyT = b'') -> None:
         """register a temporary transaction file
 
         Such files will be deleted when the transaction exits (on both
@@ -457,13 +479,13 @@
     @active
     def addfilegenerator(
         self,
-        genid,
-        filenames,
-        genfunc,
-        order=0,
-        location=b'',
-        post_finalize=False,
-    ):
+        genid: bytes,
+        filenames: Collection[HgPathT],
+        genfunc: Callable,
+        order: int = 0,
+        location: VfsKeyT = b'',
+        post_finalize: bool = False,
+    ) -> None:
         """add a function to generates some files at transaction commit
 
         The `genfunc` argument is a function capable of generating proper
@@ -495,7 +517,7 @@
         self._filegenerators[genid] = entry
 
     @active
-    def removefilegenerator(self, genid):
+    def removefilegenerator(self, genid: bytes) -> None:
         """reverse of addfilegenerator, remove a file generator function"""
         if genid in self._filegenerators:
             del self._filegenerators[genid]
@@ -545,13 +567,13 @@
         return any
 
     @active
-    def findoffset(self, file):
+    def findoffset(self, file: HgPathT) -> Optional[int]:
         if file in self._newfiles:
             return 0
         return self._offsetmap.get(file)
 
     @active
-    def readjournal(self):
+    def readjournal(self) -> List[JournalEntryT]:
         self._file.seek(0)
         entries = []
         for l in self._file.readlines():
@@ -560,7 +582,7 @@
         return entries
 
     @active
-    def replace(self, file, offset):
+    def replace(self, file: HgPathT, offset: int) -> None:
         """
         replace can only replace already committed entries
         that are not pending in the queue
@@ -582,13 +604,13 @@
         self._file.flush()
 
     @active
-    def nest(self, name=b'<unnamed>'):
+    def nest(self, name: bytes = b'<unnamed>') -> transaction:
         self._count += 1
         self._usages += 1
         self._names.append(name)
         return self
 
-    def release(self):
+    def release(self) -> None:
         if self._count > 0:
             self._usages -= 1
         if self._names:
@@ -597,10 +619,14 @@
         if self._count > 0 and self._usages == 0:
             self._abort()
 
-    def running(self):
+    def running(self) -> bool:
         return self._count > 0
 
-    def addpending(self, category, callback):
+    def addpending(
+        self,
+        category: CallbackCategoryT,
+        callback: Callable[[transaction], None],
+    ) -> None:
         """add a callback to be called when the transaction is pending
 
         The transaction will be given as callback's first argument.
@@ -611,7 +637,7 @@
         self._pendingcallback[category] = callback
 
     @active
-    def writepending(self):
+    def writepending(self) -> bool:
         """write pending file to temporary version
 
         This is used to allow hooks to view a transaction before commit"""
@@ -624,12 +650,16 @@
         return self._anypending
 
     @active
-    def hasfinalize(self, category):
+    def hasfinalize(self, category: CallbackCategoryT) -> bool:
         """check is a callback already exist for a category"""
         return category in self._finalizecallback
 
     @active
-    def addfinalize(self, category, callback):
+    def addfinalize(
+        self,
+        category: CallbackCategoryT,
+        callback: Callable[[transaction], None],
+    ) -> None:
         """add a callback to be called when the transaction is closed
 
         The transaction will be given as callback's first argument.
@@ -640,7 +670,11 @@
         self._finalizecallback[category] = callback
 
     @active
-    def addpostclose(self, category, callback):
+    def addpostclose(
+        self,
+        category: CallbackCategoryT,
+        callback: Callable[[transaction], None],
+    ) -> None:
         """add or replace a callback to be called after the transaction closed
 
         The transaction will be given as callback's first argument.
@@ -651,12 +685,19 @@
         self._postclosecallback[category] = callback
 
     @active
-    def getpostclose(self, category):
+    def getpostclose(
+        self,
+        category: CallbackCategoryT,
+    ) -> Optional[Callable[[transaction], None]]:
         """return a postclose callback added before, or None"""
         return self._postclosecallback.get(category, None)
 
     @active
-    def addabort(self, category, callback):
+    def addabort(
+        self,
+        category: CallbackCategoryT,
+        callback: Callable[[transaction], None],
+    ) -> None:
         """add a callback to be called when the transaction is aborted.
 
         The transaction will be given as the first argument to the callback.
@@ -667,7 +708,11 @@
         self._abortcallback[category] = callback
 
     @active
-    def addvalidator(self, category, callback):
+    def addvalidator(
+        self,
+        category: CallbackCategoryT,
+        callback: Callable[[transaction], None],
+    ) -> None:
         """adds a callback to be called when validating the transaction.
 
         The transaction will be given as the first argument to the callback.
@@ -676,7 +721,7 @@
         self._validatecallback[category] = callback
 
     @active
-    def close(self):
+    def close(self) -> None:
         '''commit the transaction'''
         if self._count == 1:
             for category in sorted(self._validatecallback):
@@ -758,14 +803,14 @@
         self._postclosecallback = None
 
     @active
-    def abort(self):
+    def abort(self) -> None:
         """abort the transaction (generally called on error, or when the
         transaction is not explicitly committed before going out of
         scope)"""
         self._abort()
 
     @active
-    def add_journal(self, vfs_id, path):
+    def add_journal(self, vfs_id: VfsKeyT, path: HgPathT) -> None:
         self._journal_files.append((vfs_id, path))
 
     def _writeundo(self):