Patchwork [1,of,2,V3] error: make HintException a mix-in class not derived from BaseException (API)

login
register
mail settings
Submitter Yuya Nishihara
Date July 11, 2016, 2:28 p.m.
Message ID <5a15266e4b16eb9dba59.1468247298@mimosa>
Download mbox | patch
Permalink /patch/15794/
State Accepted
Headers show

Comments

Yuya Nishihara - July 11, 2016, 2:28 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1468042110 -32400
#      Sat Jul 09 14:28:30 2016 +0900
# Node ID 5a15266e4b16eb9dba59fa561a2c3b6d3214db4b
# Parent  4b16a5bd99484cac96ade9af76e6deee1fc57b54
error: make HintException a mix-in class not derived from BaseException (API)

HintException is unrelated to the hierarchy of errors. It is an implementation
detail whether a class inherits from HintException or not, a sort of "private
inheritance" in C++.

New Hint isn't an exception class, which prevents catching error by its type:

    try:
        dosomething()
    except error.Hint:
        pass

Unfortunately, this passes on PyPy 5.3.1, but not on Python 2, and raises more
detailed TypeError on Python 3.

Patch

diff --git a/mercurial/error.py b/mercurial/error.py
--- a/mercurial/error.py
+++ b/mercurial/error.py
@@ -15,12 +15,17 @@  from __future__ import absolute_import
 
 # Do not import anything here, please
 
-class HintException(Exception):
+class Hint(object):
+    """Mix-in to provide a hint of an error
+
+    This should come first in the inheritance list to consume **kw and pass
+    only *args to the exception class.
+    """
     def __init__(self, *args, **kw):
-        Exception.__init__(self, *args)
+        super(Hint, self).__init__(*args)
         self.hint = kw.get('hint')
 
-class RevlogError(HintException):
+class RevlogError(Hint, Exception):
     pass
 
 class FilteredIndexError(IndexError):
@@ -50,10 +55,10 @@  class ManifestLookupError(LookupError):
 class CommandError(Exception):
     """Exception raised on errors in parsing the command line."""
 
-class InterventionRequired(HintException):
+class InterventionRequired(Hint, Exception):
     """Exception raised when a command requires human intervention."""
 
-class Abort(HintException):
+class Abort(Hint, Exception):
     """Raised if a command needs to print an error and exit."""
 
 class HookLoadError(Abort):
@@ -87,10 +92,10 @@  class ResponseExpected(Abort):
         from .i18n import _
         Abort.__init__(self, _('response expected'))
 
-class OutOfBandError(HintException):
+class OutOfBandError(Hint, Exception):
     """Exception raised when a remote repo reports failure"""
 
-class ParseError(HintException):
+class ParseError(Hint, Exception):
     """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
 
 class UnknownIdentifier(ParseError):
@@ -102,7 +107,7 @@  class UnknownIdentifier(ParseError):
         self.function = function
         self.symbols = symbols
 
-class RepoError(HintException):
+class RepoError(Hint, Exception):
     pass
 
 class RepoLookupError(RepoError):