##// END OF EJS Templates
py3: add inline comment about encoding issue of str(Abort())
Yuya Nishihara -
r44121:ca3dca41 5.2 stable
parent child Browse files
Show More
@@ -1,435 +1,438 b''
1 1 # error.py - Mercurial exceptions
2 2 #
3 3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 """Mercurial exceptions.
9 9
10 10 This allows us to catch exceptions at higher levels without forcing
11 11 imports.
12 12 """
13 13
14 14 from __future__ import absolute_import
15 15
16 16 # Do not import anything but pycompat here, please
17 17 from . import pycompat
18 18
19 19
20 20 def _tobytes(exc):
21 21 """Byte-stringify exception in the same way as BaseException_str()"""
22 22 if not exc.args:
23 23 return b''
24 24 if len(exc.args) == 1:
25 25 return pycompat.bytestr(exc.args[0])
26 26 return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args)
27 27
28 28
29 29 class Hint(object):
30 30 """Mix-in to provide a hint of an error
31 31
32 32 This should come first in the inheritance list to consume a hint and
33 33 pass remaining arguments to the exception class.
34 34 """
35 35
36 36 def __init__(self, *args, **kw):
37 37 self.hint = kw.pop(r'hint', None)
38 38 super(Hint, self).__init__(*args, **kw)
39 39
40 40
41 41 class StorageError(Hint, Exception):
42 42 """Raised when an error occurs in a storage layer.
43 43
44 44 Usually subclassed by a storage-specific exception.
45 45 """
46 46
47 47 __bytes__ = _tobytes
48 48
49 49
50 50 class RevlogError(StorageError):
51 51 __bytes__ = _tobytes
52 52
53 53
54 54 class SidedataHashError(RevlogError):
55 55 def __init__(self, key, expected, got):
56 56 self.sidedatakey = key
57 57 self.expecteddigest = expected
58 58 self.actualdigest = got
59 59
60 60
61 61 class FilteredIndexError(IndexError):
62 62 __bytes__ = _tobytes
63 63
64 64
65 65 class LookupError(RevlogError, KeyError):
66 66 def __init__(self, name, index, message):
67 67 self.name = name
68 68 self.index = index
69 69 # this can't be called 'message' because at least some installs of
70 70 # Python 2.6+ complain about the 'message' property being deprecated
71 71 self.lookupmessage = message
72 72 if isinstance(name, bytes) and len(name) == 20:
73 73 from .node import short
74 74
75 75 name = short(name)
76 76 RevlogError.__init__(self, b'%s@%s: %s' % (index, name, message))
77 77
78 78 def __bytes__(self):
79 79 return RevlogError.__bytes__(self)
80 80
81 81 def __str__(self):
82 82 return RevlogError.__str__(self)
83 83
84 84
85 85 class AmbiguousPrefixLookupError(LookupError):
86 86 pass
87 87
88 88
89 89 class FilteredLookupError(LookupError):
90 90 pass
91 91
92 92
93 93 class ManifestLookupError(LookupError):
94 94 pass
95 95
96 96
97 97 class CommandError(Exception):
98 98 """Exception raised on errors in parsing the command line."""
99 99
100 100 __bytes__ = _tobytes
101 101
102 102
103 103 class InterventionRequired(Hint, Exception):
104 104 """Exception raised when a command requires human intervention."""
105 105
106 106 __bytes__ = _tobytes
107 107
108 108
109 109 class Abort(Hint, Exception):
110 110 """Raised if a command needs to print an error and exit."""
111 111
112 112 __bytes__ = _tobytes
113 113
114 114 if pycompat.ispy3:
115 115
116 116 def __str__(self):
117 # the output would be unreadable if the message was translated,
118 # but do not replace it with encoding.strfromlocal(), which
119 # may raise another exception.
117 120 return pycompat.sysstr(self.__bytes__())
118 121
119 122
120 123 class HookLoadError(Abort):
121 124 """raised when loading a hook fails, aborting an operation
122 125
123 126 Exists to allow more specialized catching."""
124 127
125 128
126 129 class HookAbort(Abort):
127 130 """raised when a validation hook fails, aborting an operation
128 131
129 132 Exists to allow more specialized catching."""
130 133
131 134
132 135 class ConfigError(Abort):
133 136 """Exception raised when parsing config files"""
134 137
135 138
136 139 class UpdateAbort(Abort):
137 140 """Raised when an update is aborted for destination issue"""
138 141
139 142
140 143 class MergeDestAbort(Abort):
141 144 """Raised when an update is aborted for destination issues"""
142 145
143 146
144 147 class NoMergeDestAbort(MergeDestAbort):
145 148 """Raised when an update is aborted because there is nothing to merge"""
146 149
147 150
148 151 class ManyMergeDestAbort(MergeDestAbort):
149 152 """Raised when an update is aborted because destination is ambiguous"""
150 153
151 154
152 155 class ResponseExpected(Abort):
153 156 """Raised when an EOF is received for a prompt"""
154 157
155 158 def __init__(self):
156 159 from .i18n import _
157 160
158 161 Abort.__init__(self, _(b'response expected'))
159 162
160 163
161 164 class OutOfBandError(Hint, Exception):
162 165 """Exception raised when a remote repo reports failure"""
163 166
164 167 __bytes__ = _tobytes
165 168
166 169
167 170 class ParseError(Hint, Exception):
168 171 """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
169 172
170 173 __bytes__ = _tobytes
171 174
172 175
173 176 class PatchError(Exception):
174 177 __bytes__ = _tobytes
175 178
176 179
177 180 class UnknownIdentifier(ParseError):
178 181 """Exception raised when a {rev,file}set references an unknown identifier"""
179 182
180 183 def __init__(self, function, symbols):
181 184 from .i18n import _
182 185
183 186 ParseError.__init__(self, _(b"unknown identifier: %s") % function)
184 187 self.function = function
185 188 self.symbols = symbols
186 189
187 190
188 191 class RepoError(Hint, Exception):
189 192 __bytes__ = _tobytes
190 193
191 194
192 195 class RepoLookupError(RepoError):
193 196 pass
194 197
195 198
196 199 class FilteredRepoLookupError(RepoLookupError):
197 200 pass
198 201
199 202
200 203 class CapabilityError(RepoError):
201 204 pass
202 205
203 206
204 207 class RequirementError(RepoError):
205 208 """Exception raised if .hg/requires has an unknown entry."""
206 209
207 210
208 211 class StdioError(IOError):
209 212 """Raised if I/O to stdout or stderr fails"""
210 213
211 214 def __init__(self, err):
212 215 IOError.__init__(self, err.errno, err.strerror)
213 216
214 217 # no __bytes__() because error message is derived from the standard IOError
215 218
216 219
217 220 class UnsupportedMergeRecords(Abort):
218 221 def __init__(self, recordtypes):
219 222 from .i18n import _
220 223
221 224 self.recordtypes = sorted(recordtypes)
222 225 s = b' '.join(self.recordtypes)
223 226 Abort.__init__(
224 227 self,
225 228 _(b'unsupported merge state records: %s') % s,
226 229 hint=_(
227 230 b'see https://mercurial-scm.org/wiki/MergeStateRecords for '
228 231 b'more information'
229 232 ),
230 233 )
231 234
232 235
233 236 class UnknownVersion(Abort):
234 237 """generic exception for aborting from an encounter with an unknown version
235 238 """
236 239
237 240 def __init__(self, msg, hint=None, version=None):
238 241 self.version = version
239 242 super(UnknownVersion, self).__init__(msg, hint=hint)
240 243
241 244
242 245 class LockError(IOError):
243 246 def __init__(self, errno, strerror, filename, desc):
244 247 IOError.__init__(self, errno, strerror, filename)
245 248 self.desc = desc
246 249
247 250 # no __bytes__() because error message is derived from the standard IOError
248 251
249 252
250 253 class LockHeld(LockError):
251 254 def __init__(self, errno, filename, desc, locker):
252 255 LockError.__init__(self, errno, b'Lock held', filename, desc)
253 256 self.locker = locker
254 257
255 258
256 259 class LockUnavailable(LockError):
257 260 pass
258 261
259 262
260 263 # LockError is for errors while acquiring the lock -- this is unrelated
261 264 class LockInheritanceContractViolation(RuntimeError):
262 265 __bytes__ = _tobytes
263 266
264 267
265 268 class ResponseError(Exception):
266 269 """Raised to print an error with part of output and exit."""
267 270
268 271 __bytes__ = _tobytes
269 272
270 273
271 274 class UnknownCommand(Exception):
272 275 """Exception raised if command is not in the command table."""
273 276
274 277 __bytes__ = _tobytes
275 278
276 279
277 280 class AmbiguousCommand(Exception):
278 281 """Exception raised if command shortcut matches more than one command."""
279 282
280 283 __bytes__ = _tobytes
281 284
282 285
283 286 # derived from KeyboardInterrupt to simplify some breakout code
284 287 class SignalInterrupt(KeyboardInterrupt):
285 288 """Exception raised on SIGTERM and SIGHUP."""
286 289
287 290
288 291 class SignatureError(Exception):
289 292 __bytes__ = _tobytes
290 293
291 294
292 295 class PushRaced(RuntimeError):
293 296 """An exception raised during unbundling that indicate a push race"""
294 297
295 298 __bytes__ = _tobytes
296 299
297 300
298 301 class ProgrammingError(Hint, RuntimeError):
299 302 """Raised if a mercurial (core or extension) developer made a mistake"""
300 303
301 304 def __init__(self, msg, *args, **kwargs):
302 305 # On Python 3, turn the message back into a string since this is
303 306 # an internal-only error that won't be printed except in a
304 307 # stack traces.
305 308 msg = pycompat.sysstr(msg)
306 309 super(ProgrammingError, self).__init__(msg, *args, **kwargs)
307 310
308 311 __bytes__ = _tobytes
309 312
310 313
311 314 class WdirUnsupported(Exception):
312 315 """An exception which is raised when 'wdir()' is not supported"""
313 316
314 317 __bytes__ = _tobytes
315 318
316 319
317 320 # bundle2 related errors
318 321 class BundleValueError(ValueError):
319 322 """error raised when bundle2 cannot be processed"""
320 323
321 324 __bytes__ = _tobytes
322 325
323 326
324 327 class BundleUnknownFeatureError(BundleValueError):
325 328 def __init__(self, parttype=None, params=(), values=()):
326 329 self.parttype = parttype
327 330 self.params = params
328 331 self.values = values
329 332 if self.parttype is None:
330 333 msg = b'Stream Parameter'
331 334 else:
332 335 msg = parttype
333 336 entries = self.params
334 337 if self.params and self.values:
335 338 assert len(self.params) == len(self.values)
336 339 entries = []
337 340 for idx, par in enumerate(self.params):
338 341 val = self.values[idx]
339 342 if val is None:
340 343 entries.append(val)
341 344 else:
342 345 entries.append(b"%s=%r" % (par, pycompat.maybebytestr(val)))
343 346 if entries:
344 347 msg = b'%s - %s' % (msg, b', '.join(entries))
345 348 ValueError.__init__(self, msg)
346 349
347 350
348 351 class ReadOnlyPartError(RuntimeError):
349 352 """error raised when code tries to alter a part being generated"""
350 353
351 354 __bytes__ = _tobytes
352 355
353 356
354 357 class PushkeyFailed(Abort):
355 358 """error raised when a pushkey part failed to update a value"""
356 359
357 360 def __init__(
358 361 self, partid, namespace=None, key=None, new=None, old=None, ret=None
359 362 ):
360 363 self.partid = partid
361 364 self.namespace = namespace
362 365 self.key = key
363 366 self.new = new
364 367 self.old = old
365 368 self.ret = ret
366 369 # no i18n expected to be processed into a better message
367 370 Abort.__init__(
368 371 self, b'failed to update value for "%s/%s"' % (namespace, key)
369 372 )
370 373
371 374
372 375 class CensoredNodeError(StorageError):
373 376 """error raised when content verification fails on a censored node
374 377
375 378 Also contains the tombstone data substituted for the uncensored data.
376 379 """
377 380
378 381 def __init__(self, filename, node, tombstone):
379 382 from .node import short
380 383
381 384 StorageError.__init__(self, b'%s:%s' % (filename, short(node)))
382 385 self.tombstone = tombstone
383 386
384 387
385 388 class CensoredBaseError(StorageError):
386 389 """error raised when a delta is rejected because its base is censored
387 390
388 391 A delta based on a censored revision must be formed as single patch
389 392 operation which replaces the entire base with new content. This ensures
390 393 the delta may be applied by clones which have not censored the base.
391 394 """
392 395
393 396
394 397 class InvalidBundleSpecification(Exception):
395 398 """error raised when a bundle specification is invalid.
396 399
397 400 This is used for syntax errors as opposed to support errors.
398 401 """
399 402
400 403 __bytes__ = _tobytes
401 404
402 405
403 406 class UnsupportedBundleSpecification(Exception):
404 407 """error raised when a bundle specification is not supported."""
405 408
406 409 __bytes__ = _tobytes
407 410
408 411
409 412 class CorruptedState(Exception):
410 413 """error raised when a command is not able to read its state from file"""
411 414
412 415 __bytes__ = _tobytes
413 416
414 417
415 418 class PeerTransportError(Abort):
416 419 """Transport-level I/O error when communicating with a peer repo."""
417 420
418 421
419 422 class InMemoryMergeConflictsError(Exception):
420 423 """Exception raised when merge conflicts arose during an in-memory merge."""
421 424
422 425 __bytes__ = _tobytes
423 426
424 427
425 428 class WireprotoCommandError(Exception):
426 429 """Represents an error during execution of a wire protocol command.
427 430
428 431 Should only be thrown by wire protocol version 2 commands.
429 432
430 433 The error is a formatter string and an optional iterable of arguments.
431 434 """
432 435
433 436 def __init__(self, message, args=None):
434 437 self.message = message
435 438 self.messageargs = args
General Comments 0
You need to be logged in to leave comments. Login now