Mercurial > hg > mercurial-source
changeset 33399:6df193b5c437
py3: implement __bytes__() on most of our exception classes
We store bytes in exc.args, which should be translated to a byte string
without encode/decode dance.
IOError subclasses are unchanged for now. We'll need to decide how our
IOErrors should be caught.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Thu, 01 Jun 2017 22:43:24 +0900 |
parents | c9318beb7c1a |
children | e48cb1c7a902 |
files | mercurial/error.py tests/test-py3-commands.t |
diffstat | 2 files changed, 43 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/error.py +++ b/mercurial/error.py @@ -13,7 +13,16 @@ from __future__ import absolute_import -# Do not import anything here, please +# Do not import anything but pycompat here, please +from . import pycompat + +def _tobytes(exc): + """Byte-stringify exception in the same way as BaseException_str()""" + if not exc.args: + return b'' + if len(exc.args) == 1: + return pycompat.bytestr(exc.args[0]) + return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args) class Hint(object): """Mix-in to provide a hint of an error @@ -26,10 +35,10 @@ super(Hint, self).__init__(*args, **kw) class RevlogError(Hint, Exception): - pass + __bytes__ = _tobytes class FilteredIndexError(IndexError): - pass + __bytes__ = _tobytes class LookupError(RevlogError, KeyError): def __init__(self, name, index, message): @@ -43,6 +52,9 @@ name = short(name) RevlogError.__init__(self, '%s@%s: %s' % (index, name, message)) + def __bytes__(self): + return RevlogError.__bytes__(self) + def __str__(self): return RevlogError.__str__(self) @@ -54,12 +66,15 @@ class CommandError(Exception): """Exception raised on errors in parsing the command line.""" + __bytes__ = _tobytes class InterventionRequired(Hint, Exception): """Exception raised when a command requires human intervention.""" + __bytes__ = _tobytes class Abort(Hint, Exception): """Raised if a command needs to print an error and exit.""" + __bytes__ = _tobytes class HookLoadError(Abort): """raised when loading a hook fails, aborting an operation @@ -94,9 +109,11 @@ class OutOfBandError(Hint, Exception): """Exception raised when a remote repo reports failure""" + __bytes__ = _tobytes class ParseError(Hint, Exception): """Raised when parsing config files and {rev,file}sets (msg[, pos])""" + __bytes__ = _tobytes class UnknownIdentifier(ParseError): """Exception raised when a {rev,file}set references an unknown identifier""" @@ -108,7 +125,7 @@ self.symbols = symbols class RepoError(Hint, Exception): - pass + __bytes__ = _tobytes class RepoLookupError(RepoError): pass @@ -128,6 +145,8 @@ def __init__(self, err): IOError.__init__(self, err.errno, err.strerror) + # no __bytes__() because error message is derived from the standard IOError + class UnsupportedMergeRecords(Abort): def __init__(self, recordtypes): from .i18n import _ @@ -151,6 +170,8 @@ IOError.__init__(self, errno, strerror, filename) self.desc = desc + # no __bytes__() because error message is derived from the standard IOError + class LockHeld(LockError): def __init__(self, errno, filename, desc, locker): LockError.__init__(self, errno, 'Lock held', filename, desc) @@ -161,36 +182,43 @@ # LockError is for errors while acquiring the lock -- this is unrelated class LockInheritanceContractViolation(RuntimeError): - pass + __bytes__ = _tobytes class ResponseError(Exception): """Raised to print an error with part of output and exit.""" + __bytes__ = _tobytes class UnknownCommand(Exception): """Exception raised if command is not in the command table.""" + __bytes__ = _tobytes class AmbiguousCommand(Exception): """Exception raised if command shortcut matches more than one command.""" + __bytes__ = _tobytes # derived from KeyboardInterrupt to simplify some breakout code class SignalInterrupt(KeyboardInterrupt): """Exception raised on SIGTERM and SIGHUP.""" class SignatureError(Exception): - pass + __bytes__ = _tobytes class PushRaced(RuntimeError): """An exception raised during unbundling that indicate a push race""" + __bytes__ = _tobytes class ProgrammingError(Hint, RuntimeError): """Raised if a mercurial (core or extension) developer made a mistake""" + __bytes__ = _tobytes class WdirUnsupported(Exception): """An exception which is raised when 'wdir()' is not supported""" + __bytes__ = _tobytes # bundle2 related errors class BundleValueError(ValueError): """error raised when bundle2 cannot be processed""" + __bytes__ = _tobytes class BundleUnknownFeatureError(BundleValueError): def __init__(self, parttype=None, params=(), values=()): @@ -217,6 +245,7 @@ class ReadOnlyPartError(RuntimeError): """error raised when code tries to alter a part being generated""" + __bytes__ = _tobytes class PushkeyFailed(Abort): """error raised when a pushkey part failed to update a value""" @@ -257,12 +286,15 @@ This is used for syntax errors as opposed to support errors. """ + __bytes__ = _tobytes class UnsupportedBundleSpecification(Exception): """error raised when a bundle specification is not supported.""" + __bytes__ = _tobytes class CorruptedState(Exception): """error raised when a command is not able to read its state from file""" + __bytes__ = _tobytes class PeerTransportError(Abort): """Transport-level I/O error when communicating with a peer repo."""
--- a/tests/test-py3-commands.t +++ b/tests/test-py3-commands.t @@ -151,6 +151,11 @@ options ([+] can be repeated): (some details hidden, use --verbose to show complete help) + $ $PYTHON3 $HGBIN help -k notopic + abort: no matches + (try 'hg help' for a list of topics) + [255] + Prove the repo is valid using the Python 2 `hg`: $ hg verify checking changesets