Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/error.py @ 32639: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 | 19df975eb555 |
children | 61714510220d |
comparison
equal
deleted
inserted
replaced
32638:c9318beb7c1a | 32639:6df193b5c437 |
---|---|
11 imports. | 11 imports. |
12 """ | 12 """ |
13 | 13 |
14 from __future__ import absolute_import | 14 from __future__ import absolute_import |
15 | 15 |
16 # Do not import anything here, please | 16 # Do not import anything but pycompat here, please |
17 from . import pycompat | |
18 | |
19 def _tobytes(exc): | |
20 """Byte-stringify exception in the same way as BaseException_str()""" | |
21 if not exc.args: | |
22 return b'' | |
23 if len(exc.args) == 1: | |
24 return pycompat.bytestr(exc.args[0]) | |
25 return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args) | |
17 | 26 |
18 class Hint(object): | 27 class Hint(object): |
19 """Mix-in to provide a hint of an error | 28 """Mix-in to provide a hint of an error |
20 | 29 |
21 This should come first in the inheritance list to consume a hint and | 30 This should come first in the inheritance list to consume a hint and |
24 def __init__(self, *args, **kw): | 33 def __init__(self, *args, **kw): |
25 self.hint = kw.pop(r'hint', None) | 34 self.hint = kw.pop(r'hint', None) |
26 super(Hint, self).__init__(*args, **kw) | 35 super(Hint, self).__init__(*args, **kw) |
27 | 36 |
28 class RevlogError(Hint, Exception): | 37 class RevlogError(Hint, Exception): |
29 pass | 38 __bytes__ = _tobytes |
30 | 39 |
31 class FilteredIndexError(IndexError): | 40 class FilteredIndexError(IndexError): |
32 pass | 41 __bytes__ = _tobytes |
33 | 42 |
34 class LookupError(RevlogError, KeyError): | 43 class LookupError(RevlogError, KeyError): |
35 def __init__(self, name, index, message): | 44 def __init__(self, name, index, message): |
36 self.name = name | 45 self.name = name |
37 self.index = index | 46 self.index = index |
41 if isinstance(name, str) and len(name) == 20: | 50 if isinstance(name, str) and len(name) == 20: |
42 from .node import short | 51 from .node import short |
43 name = short(name) | 52 name = short(name) |
44 RevlogError.__init__(self, '%s@%s: %s' % (index, name, message)) | 53 RevlogError.__init__(self, '%s@%s: %s' % (index, name, message)) |
45 | 54 |
55 def __bytes__(self): | |
56 return RevlogError.__bytes__(self) | |
57 | |
46 def __str__(self): | 58 def __str__(self): |
47 return RevlogError.__str__(self) | 59 return RevlogError.__str__(self) |
48 | 60 |
49 class FilteredLookupError(LookupError): | 61 class FilteredLookupError(LookupError): |
50 pass | 62 pass |
52 class ManifestLookupError(LookupError): | 64 class ManifestLookupError(LookupError): |
53 pass | 65 pass |
54 | 66 |
55 class CommandError(Exception): | 67 class CommandError(Exception): |
56 """Exception raised on errors in parsing the command line.""" | 68 """Exception raised on errors in parsing the command line.""" |
69 __bytes__ = _tobytes | |
57 | 70 |
58 class InterventionRequired(Hint, Exception): | 71 class InterventionRequired(Hint, Exception): |
59 """Exception raised when a command requires human intervention.""" | 72 """Exception raised when a command requires human intervention.""" |
73 __bytes__ = _tobytes | |
60 | 74 |
61 class Abort(Hint, Exception): | 75 class Abort(Hint, Exception): |
62 """Raised if a command needs to print an error and exit.""" | 76 """Raised if a command needs to print an error and exit.""" |
77 __bytes__ = _tobytes | |
63 | 78 |
64 class HookLoadError(Abort): | 79 class HookLoadError(Abort): |
65 """raised when loading a hook fails, aborting an operation | 80 """raised when loading a hook fails, aborting an operation |
66 | 81 |
67 Exists to allow more specialized catching.""" | 82 Exists to allow more specialized catching.""" |
92 from .i18n import _ | 107 from .i18n import _ |
93 Abort.__init__(self, _('response expected')) | 108 Abort.__init__(self, _('response expected')) |
94 | 109 |
95 class OutOfBandError(Hint, Exception): | 110 class OutOfBandError(Hint, Exception): |
96 """Exception raised when a remote repo reports failure""" | 111 """Exception raised when a remote repo reports failure""" |
112 __bytes__ = _tobytes | |
97 | 113 |
98 class ParseError(Hint, Exception): | 114 class ParseError(Hint, Exception): |
99 """Raised when parsing config files and {rev,file}sets (msg[, pos])""" | 115 """Raised when parsing config files and {rev,file}sets (msg[, pos])""" |
116 __bytes__ = _tobytes | |
100 | 117 |
101 class UnknownIdentifier(ParseError): | 118 class UnknownIdentifier(ParseError): |
102 """Exception raised when a {rev,file}set references an unknown identifier""" | 119 """Exception raised when a {rev,file}set references an unknown identifier""" |
103 | 120 |
104 def __init__(self, function, symbols): | 121 def __init__(self, function, symbols): |
106 ParseError.__init__(self, _("unknown identifier: %s") % function) | 123 ParseError.__init__(self, _("unknown identifier: %s") % function) |
107 self.function = function | 124 self.function = function |
108 self.symbols = symbols | 125 self.symbols = symbols |
109 | 126 |
110 class RepoError(Hint, Exception): | 127 class RepoError(Hint, Exception): |
111 pass | 128 __bytes__ = _tobytes |
112 | 129 |
113 class RepoLookupError(RepoError): | 130 class RepoLookupError(RepoError): |
114 pass | 131 pass |
115 | 132 |
116 class FilteredRepoLookupError(RepoLookupError): | 133 class FilteredRepoLookupError(RepoLookupError): |
125 class StdioError(IOError): | 142 class StdioError(IOError): |
126 """Raised if I/O to stdout or stderr fails""" | 143 """Raised if I/O to stdout or stderr fails""" |
127 | 144 |
128 def __init__(self, err): | 145 def __init__(self, err): |
129 IOError.__init__(self, err.errno, err.strerror) | 146 IOError.__init__(self, err.errno, err.strerror) |
147 | |
148 # no __bytes__() because error message is derived from the standard IOError | |
130 | 149 |
131 class UnsupportedMergeRecords(Abort): | 150 class UnsupportedMergeRecords(Abort): |
132 def __init__(self, recordtypes): | 151 def __init__(self, recordtypes): |
133 from .i18n import _ | 152 from .i18n import _ |
134 self.recordtypes = sorted(recordtypes) | 153 self.recordtypes = sorted(recordtypes) |
149 class LockError(IOError): | 168 class LockError(IOError): |
150 def __init__(self, errno, strerror, filename, desc): | 169 def __init__(self, errno, strerror, filename, desc): |
151 IOError.__init__(self, errno, strerror, filename) | 170 IOError.__init__(self, errno, strerror, filename) |
152 self.desc = desc | 171 self.desc = desc |
153 | 172 |
173 # no __bytes__() because error message is derived from the standard IOError | |
174 | |
154 class LockHeld(LockError): | 175 class LockHeld(LockError): |
155 def __init__(self, errno, filename, desc, locker): | 176 def __init__(self, errno, filename, desc, locker): |
156 LockError.__init__(self, errno, 'Lock held', filename, desc) | 177 LockError.__init__(self, errno, 'Lock held', filename, desc) |
157 self.locker = locker | 178 self.locker = locker |
158 | 179 |
159 class LockUnavailable(LockError): | 180 class LockUnavailable(LockError): |
160 pass | 181 pass |
161 | 182 |
162 # LockError is for errors while acquiring the lock -- this is unrelated | 183 # LockError is for errors while acquiring the lock -- this is unrelated |
163 class LockInheritanceContractViolation(RuntimeError): | 184 class LockInheritanceContractViolation(RuntimeError): |
164 pass | 185 __bytes__ = _tobytes |
165 | 186 |
166 class ResponseError(Exception): | 187 class ResponseError(Exception): |
167 """Raised to print an error with part of output and exit.""" | 188 """Raised to print an error with part of output and exit.""" |
189 __bytes__ = _tobytes | |
168 | 190 |
169 class UnknownCommand(Exception): | 191 class UnknownCommand(Exception): |
170 """Exception raised if command is not in the command table.""" | 192 """Exception raised if command is not in the command table.""" |
193 __bytes__ = _tobytes | |
171 | 194 |
172 class AmbiguousCommand(Exception): | 195 class AmbiguousCommand(Exception): |
173 """Exception raised if command shortcut matches more than one command.""" | 196 """Exception raised if command shortcut matches more than one command.""" |
197 __bytes__ = _tobytes | |
174 | 198 |
175 # derived from KeyboardInterrupt to simplify some breakout code | 199 # derived from KeyboardInterrupt to simplify some breakout code |
176 class SignalInterrupt(KeyboardInterrupt): | 200 class SignalInterrupt(KeyboardInterrupt): |
177 """Exception raised on SIGTERM and SIGHUP.""" | 201 """Exception raised on SIGTERM and SIGHUP.""" |
178 | 202 |
179 class SignatureError(Exception): | 203 class SignatureError(Exception): |
180 pass | 204 __bytes__ = _tobytes |
181 | 205 |
182 class PushRaced(RuntimeError): | 206 class PushRaced(RuntimeError): |
183 """An exception raised during unbundling that indicate a push race""" | 207 """An exception raised during unbundling that indicate a push race""" |
208 __bytes__ = _tobytes | |
184 | 209 |
185 class ProgrammingError(Hint, RuntimeError): | 210 class ProgrammingError(Hint, RuntimeError): |
186 """Raised if a mercurial (core or extension) developer made a mistake""" | 211 """Raised if a mercurial (core or extension) developer made a mistake""" |
212 __bytes__ = _tobytes | |
187 | 213 |
188 class WdirUnsupported(Exception): | 214 class WdirUnsupported(Exception): |
189 """An exception which is raised when 'wdir()' is not supported""" | 215 """An exception which is raised when 'wdir()' is not supported""" |
216 __bytes__ = _tobytes | |
190 | 217 |
191 # bundle2 related errors | 218 # bundle2 related errors |
192 class BundleValueError(ValueError): | 219 class BundleValueError(ValueError): |
193 """error raised when bundle2 cannot be processed""" | 220 """error raised when bundle2 cannot be processed""" |
221 __bytes__ = _tobytes | |
194 | 222 |
195 class BundleUnknownFeatureError(BundleValueError): | 223 class BundleUnknownFeatureError(BundleValueError): |
196 def __init__(self, parttype=None, params=(), values=()): | 224 def __init__(self, parttype=None, params=(), values=()): |
197 self.parttype = parttype | 225 self.parttype = parttype |
198 self.params = params | 226 self.params = params |
215 msg = '%s - %s' % (msg, ', '.join(entries)) | 243 msg = '%s - %s' % (msg, ', '.join(entries)) |
216 ValueError.__init__(self, msg) | 244 ValueError.__init__(self, msg) |
217 | 245 |
218 class ReadOnlyPartError(RuntimeError): | 246 class ReadOnlyPartError(RuntimeError): |
219 """error raised when code tries to alter a part being generated""" | 247 """error raised when code tries to alter a part being generated""" |
248 __bytes__ = _tobytes | |
220 | 249 |
221 class PushkeyFailed(Abort): | 250 class PushkeyFailed(Abort): |
222 """error raised when a pushkey part failed to update a value""" | 251 """error raised when a pushkey part failed to update a value""" |
223 | 252 |
224 def __init__(self, partid, namespace=None, key=None, new=None, old=None, | 253 def __init__(self, partid, namespace=None, key=None, new=None, old=None, |
255 class InvalidBundleSpecification(Exception): | 284 class InvalidBundleSpecification(Exception): |
256 """error raised when a bundle specification is invalid. | 285 """error raised when a bundle specification is invalid. |
257 | 286 |
258 This is used for syntax errors as opposed to support errors. | 287 This is used for syntax errors as opposed to support errors. |
259 """ | 288 """ |
289 __bytes__ = _tobytes | |
260 | 290 |
261 class UnsupportedBundleSpecification(Exception): | 291 class UnsupportedBundleSpecification(Exception): |
262 """error raised when a bundle specification is not supported.""" | 292 """error raised when a bundle specification is not supported.""" |
293 __bytes__ = _tobytes | |
263 | 294 |
264 class CorruptedState(Exception): | 295 class CorruptedState(Exception): |
265 """error raised when a command is not able to read its state from file""" | 296 """error raised when a command is not able to read its state from file""" |
297 __bytes__ = _tobytes | |
266 | 298 |
267 class PeerTransportError(Abort): | 299 class PeerTransportError(Abort): |
268 """Transport-level I/O error when communicating with a peer repo.""" | 300 """Transport-level I/O error when communicating with a peer repo.""" |