typing: add type hints to mercurial/error.py
authorMatt Harbison <matt_harbison@yahoo.com>
Thu, 25 Mar 2021 18:59:14 -0400
changeset 46899 8b6e36e4b553
parent 46898 e1d75c514ced
child 46900 64400d05db1e
typing: add type hints to mercurial/error.py The only slightly unusual things here are that `location` is passed to `ParseError` and both bytes and an int (so this accepts both), and the message passed `ProgrammingError` is immediately converted to str. Therefore it is typed as `AnyStr`, because there are a couple of instances that are already passed as str. There are a couple of places where bytes are being passed to builtin exceptions that might need to be converted to str. Differential Revision: https://phab.mercurial-scm.org/D10274
mercurial/error.py
--- a/mercurial/error.py	Fri Mar 19 00:36:26 2021 -0400
+++ b/mercurial/error.py	Thu Mar 25 18:59:14 2021 -0400
@@ -20,7 +20,13 @@
 
 if pycompat.TYPE_CHECKING:
     from typing import (
+        Any,
+        AnyStr,
+        Iterable,
+        List,
         Optional,
+        Sequence,
+        Union,
     )
 
 
@@ -109,6 +115,7 @@
     """Exception raised on errors in parsing the command line."""
 
     def __init__(self, command, message):
+        # type: (bytes, bytes) -> None
         self.command = command
         self.message = message
         super(CommandError, self).__init__()
@@ -120,6 +127,7 @@
     """Exception raised if command is not in the command table."""
 
     def __init__(self, command, all_commands=None):
+        # type: (bytes, Optional[List[bytes]]) -> None
         self.command = command
         self.all_commands = all_commands
         super(UnknownCommand, self).__init__()
@@ -131,6 +139,7 @@
     """Exception raised if command shortcut matches more than one command."""
 
     def __init__(self, prefix, matches):
+        # type: (bytes, List[bytes]) -> None
         self.prefix = prefix
         self.matches = matches
         super(AmbiguousCommand, self).__init__()
@@ -142,6 +151,7 @@
     """Exception raised when a worker process dies."""
 
     def __init__(self, status_code):
+        # type: (int) -> None
         self.status_code = status_code
         # Pass status code to superclass just so it becomes part of __bytes__
         super(WorkerError, self).__init__(status_code)
@@ -159,6 +169,7 @@
     """Exception raised when a continuable command required merge conflict resolution."""
 
     def __init__(self, opname):
+        # type: (bytes) -> None
         from .i18n import _
 
         self.opname = opname
@@ -194,6 +205,7 @@
             return pycompat.sysstr(self.__bytes__())
 
     def format(self):
+        # type: () -> bytes
         from .i18n import _
 
         message = _(b"abort: %s\n") % self.message
@@ -247,10 +259,12 @@
     """Exception raised when parsing config files"""
 
     def __init__(self, message, location=None, hint=None):
+        # type: (bytes, Optional[bytes], Optional[bytes]) -> None
         super(ConfigError, self).__init__(message, hint=hint)
         self.location = location
 
     def format(self):
+        # type: () -> bytes
         from .i18n import _
 
         if self.location is not None:
@@ -300,10 +314,12 @@
     """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
 
     def __init__(self, message, location=None, hint=None):
+        # type: (bytes, Optional[Union[bytes, int]], Optional[bytes]) -> None
         super(ParseError, self).__init__(message, hint=hint)
         self.location = location
 
     def format(self):
+        # type: () -> bytes
         from .i18n import _
 
         if self.location is not None:
@@ -323,6 +339,7 @@
 
 
 def getsimilar(symbols, value):
+    # type: (Iterable[bytes], bytes) -> List[bytes]
     sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
     # The cutoff for similarity here is pretty arbitrary. It should
     # probably be investigated and tweaked.
@@ -330,6 +347,7 @@
 
 
 def similarity_hint(similar):
+    # type: (List[bytes]) -> Optional[bytes]
     from .i18n import _
 
     if len(similar) == 1:
@@ -345,6 +363,7 @@
     """Exception raised when a {rev,file}set references an unknown identifier"""
 
     def __init__(self, function, symbols):
+        # type: (bytes, Iterable[bytes]) -> None
         from .i18n import _
 
         similar = getsimilar(symbols, function)
@@ -379,6 +398,7 @@
     """Raised if I/O to stdout or stderr fails"""
 
     def __init__(self, err):
+        # type: (IOError) -> None
         IOError.__init__(self, err.errno, err.strerror)
 
     # no __bytes__() because error message is derived from the standard IOError
@@ -386,6 +406,7 @@
 
 class UnsupportedMergeRecords(Abort):
     def __init__(self, recordtypes):
+        # type: (Iterable[bytes]) -> None
         from .i18n import _
 
         self.recordtypes = sorted(recordtypes)
@@ -404,12 +425,15 @@
     """generic exception for aborting from an encounter with an unknown version"""
 
     def __init__(self, msg, hint=None, version=None):
+        # type: (bytes, Optional[bytes], Optional[bytes]) -> None
         self.version = version
         super(UnknownVersion, self).__init__(msg, hint=hint)
 
 
 class LockError(IOError):
     def __init__(self, errno, strerror, filename, desc):
+        # TODO: figure out if this should be bytes or str
+        # _type: (int, str, str, bytes) -> None
         IOError.__init__(self, errno, strerror, filename)
         self.desc = desc
 
@@ -456,6 +480,7 @@
     """Raised if a mercurial (core or extension) developer made a mistake"""
 
     def __init__(self, msg, *args, **kwargs):
+        # type: (AnyStr, Any, Any) -> None
         # On Python 3, turn the message back into a string since this is
         # an internal-only error that won't be printed except in a
         # stack traces.
@@ -499,7 +524,7 @@
                     entries.append(b"%s=%r" % (par, pycompat.maybebytestr(val)))
         if entries:
             msg = b'%s - %s' % (msg, b', '.join(entries))
-        ValueError.__init__(self, msg)
+        ValueError.__init__(self, msg)  # TODO: convert to str?
 
 
 class ReadOnlyPartError(RuntimeError):
@@ -533,6 +558,7 @@
     """
 
     def __init__(self, filename, node, tombstone):
+        # type: (bytes, bytes, bytes) -> None
         from .node import short
 
         StorageError.__init__(self, b'%s:%s' % (filename, short(node)))
@@ -588,5 +614,6 @@
     """
 
     def __init__(self, message, args=None):
+        # type: (bytes, Optional[Sequence[bytes]]) -> None
         self.message = message
         self.messageargs = args