##// END OF EJS Templates
typing: add type hints to mercurial/error.py...
Matt Harbison -
r47661:8b6e36e4 default
parent child Browse files
Show More
@@ -1,592 +1,619 b''
1 # error.py - Mercurial exceptions
1 # error.py - Mercurial exceptions
2 #
2 #
3 # Copyright 2005-2008 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2008 Olivia Mackall <olivia@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """Mercurial exceptions.
8 """Mercurial exceptions.
9
9
10 This allows us to catch exceptions at higher levels without forcing
10 This allows us to catch exceptions at higher levels without forcing
11 imports.
11 imports.
12 """
12 """
13
13
14 from __future__ import absolute_import
14 from __future__ import absolute_import
15
15
16 import difflib
16 import difflib
17
17
18 # Do not import anything but pycompat here, please
18 # Do not import anything but pycompat here, please
19 from . import pycompat
19 from . import pycompat
20
20
21 if pycompat.TYPE_CHECKING:
21 if pycompat.TYPE_CHECKING:
22 from typing import (
22 from typing import (
23 Any,
24 AnyStr,
25 Iterable,
26 List,
23 Optional,
27 Optional,
28 Sequence,
29 Union,
24 )
30 )
25
31
26
32
27 def _tobytes(exc):
33 def _tobytes(exc):
28 """Byte-stringify exception in the same way as BaseException_str()"""
34 """Byte-stringify exception in the same way as BaseException_str()"""
29 if not exc.args:
35 if not exc.args:
30 return b''
36 return b''
31 if len(exc.args) == 1:
37 if len(exc.args) == 1:
32 return pycompat.bytestr(exc.args[0])
38 return pycompat.bytestr(exc.args[0])
33 return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args)
39 return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args)
34
40
35
41
36 class Hint(object):
42 class Hint(object):
37 """Mix-in to provide a hint of an error
43 """Mix-in to provide a hint of an error
38
44
39 This should come first in the inheritance list to consume a hint and
45 This should come first in the inheritance list to consume a hint and
40 pass remaining arguments to the exception class.
46 pass remaining arguments to the exception class.
41 """
47 """
42
48
43 def __init__(self, *args, **kw):
49 def __init__(self, *args, **kw):
44 self.hint = kw.pop('hint', None)
50 self.hint = kw.pop('hint', None)
45 super(Hint, self).__init__(*args, **kw)
51 super(Hint, self).__init__(*args, **kw)
46
52
47
53
48 class StorageError(Hint, Exception):
54 class StorageError(Hint, Exception):
49 """Raised when an error occurs in a storage layer.
55 """Raised when an error occurs in a storage layer.
50
56
51 Usually subclassed by a storage-specific exception.
57 Usually subclassed by a storage-specific exception.
52 """
58 """
53
59
54 __bytes__ = _tobytes
60 __bytes__ = _tobytes
55
61
56
62
57 class RevlogError(StorageError):
63 class RevlogError(StorageError):
58 pass
64 pass
59
65
60
66
61 class SidedataHashError(RevlogError):
67 class SidedataHashError(RevlogError):
62 def __init__(self, key, expected, got):
68 def __init__(self, key, expected, got):
63 self.hint = None
69 self.hint = None
64 self.sidedatakey = key
70 self.sidedatakey = key
65 self.expecteddigest = expected
71 self.expecteddigest = expected
66 self.actualdigest = got
72 self.actualdigest = got
67
73
68
74
69 class FilteredIndexError(IndexError):
75 class FilteredIndexError(IndexError):
70 __bytes__ = _tobytes
76 __bytes__ = _tobytes
71
77
72
78
73 class LookupError(RevlogError, KeyError):
79 class LookupError(RevlogError, KeyError):
74 def __init__(self, name, index, message):
80 def __init__(self, name, index, message):
75 self.name = name
81 self.name = name
76 self.index = index
82 self.index = index
77 # this can't be called 'message' because at least some installs of
83 # this can't be called 'message' because at least some installs of
78 # Python 2.6+ complain about the 'message' property being deprecated
84 # Python 2.6+ complain about the 'message' property being deprecated
79 self.lookupmessage = message
85 self.lookupmessage = message
80 if isinstance(name, bytes) and len(name) == 20:
86 if isinstance(name, bytes) and len(name) == 20:
81 from .node import hex
87 from .node import hex
82
88
83 name = hex(name)
89 name = hex(name)
84 # if name is a binary node, it can be None
90 # if name is a binary node, it can be None
85 RevlogError.__init__(
91 RevlogError.__init__(
86 self, b'%s@%s: %s' % (index, pycompat.bytestr(name), message)
92 self, b'%s@%s: %s' % (index, pycompat.bytestr(name), message)
87 )
93 )
88
94
89 def __bytes__(self):
95 def __bytes__(self):
90 return RevlogError.__bytes__(self)
96 return RevlogError.__bytes__(self)
91
97
92 def __str__(self):
98 def __str__(self):
93 return RevlogError.__str__(self)
99 return RevlogError.__str__(self)
94
100
95
101
96 class AmbiguousPrefixLookupError(LookupError):
102 class AmbiguousPrefixLookupError(LookupError):
97 pass
103 pass
98
104
99
105
100 class FilteredLookupError(LookupError):
106 class FilteredLookupError(LookupError):
101 pass
107 pass
102
108
103
109
104 class ManifestLookupError(LookupError):
110 class ManifestLookupError(LookupError):
105 pass
111 pass
106
112
107
113
108 class CommandError(Exception):
114 class CommandError(Exception):
109 """Exception raised on errors in parsing the command line."""
115 """Exception raised on errors in parsing the command line."""
110
116
111 def __init__(self, command, message):
117 def __init__(self, command, message):
118 # type: (bytes, bytes) -> None
112 self.command = command
119 self.command = command
113 self.message = message
120 self.message = message
114 super(CommandError, self).__init__()
121 super(CommandError, self).__init__()
115
122
116 __bytes__ = _tobytes
123 __bytes__ = _tobytes
117
124
118
125
119 class UnknownCommand(Exception):
126 class UnknownCommand(Exception):
120 """Exception raised if command is not in the command table."""
127 """Exception raised if command is not in the command table."""
121
128
122 def __init__(self, command, all_commands=None):
129 def __init__(self, command, all_commands=None):
130 # type: (bytes, Optional[List[bytes]]) -> None
123 self.command = command
131 self.command = command
124 self.all_commands = all_commands
132 self.all_commands = all_commands
125 super(UnknownCommand, self).__init__()
133 super(UnknownCommand, self).__init__()
126
134
127 __bytes__ = _tobytes
135 __bytes__ = _tobytes
128
136
129
137
130 class AmbiguousCommand(Exception):
138 class AmbiguousCommand(Exception):
131 """Exception raised if command shortcut matches more than one command."""
139 """Exception raised if command shortcut matches more than one command."""
132
140
133 def __init__(self, prefix, matches):
141 def __init__(self, prefix, matches):
142 # type: (bytes, List[bytes]) -> None
134 self.prefix = prefix
143 self.prefix = prefix
135 self.matches = matches
144 self.matches = matches
136 super(AmbiguousCommand, self).__init__()
145 super(AmbiguousCommand, self).__init__()
137
146
138 __bytes__ = _tobytes
147 __bytes__ = _tobytes
139
148
140
149
141 class WorkerError(Exception):
150 class WorkerError(Exception):
142 """Exception raised when a worker process dies."""
151 """Exception raised when a worker process dies."""
143
152
144 def __init__(self, status_code):
153 def __init__(self, status_code):
154 # type: (int) -> None
145 self.status_code = status_code
155 self.status_code = status_code
146 # Pass status code to superclass just so it becomes part of __bytes__
156 # Pass status code to superclass just so it becomes part of __bytes__
147 super(WorkerError, self).__init__(status_code)
157 super(WorkerError, self).__init__(status_code)
148
158
149 __bytes__ = _tobytes
159 __bytes__ = _tobytes
150
160
151
161
152 class InterventionRequired(Hint, Exception):
162 class InterventionRequired(Hint, Exception):
153 """Exception raised when a command requires human intervention."""
163 """Exception raised when a command requires human intervention."""
154
164
155 __bytes__ = _tobytes
165 __bytes__ = _tobytes
156
166
157
167
158 class ConflictResolutionRequired(InterventionRequired):
168 class ConflictResolutionRequired(InterventionRequired):
159 """Exception raised when a continuable command required merge conflict resolution."""
169 """Exception raised when a continuable command required merge conflict resolution."""
160
170
161 def __init__(self, opname):
171 def __init__(self, opname):
172 # type: (bytes) -> None
162 from .i18n import _
173 from .i18n import _
163
174
164 self.opname = opname
175 self.opname = opname
165 InterventionRequired.__init__(
176 InterventionRequired.__init__(
166 self,
177 self,
167 _(
178 _(
168 b"unresolved conflicts (see 'hg resolve', then 'hg %s --continue')"
179 b"unresolved conflicts (see 'hg resolve', then 'hg %s --continue')"
169 )
180 )
170 % opname,
181 % opname,
171 )
182 )
172
183
173
184
174 class Abort(Hint, Exception):
185 class Abort(Hint, Exception):
175 """Raised if a command needs to print an error and exit."""
186 """Raised if a command needs to print an error and exit."""
176
187
177 def __init__(self, message, hint=None):
188 def __init__(self, message, hint=None):
178 # type: (bytes, Optional[bytes]) -> None
189 # type: (bytes, Optional[bytes]) -> None
179 self.message = message
190 self.message = message
180 self.hint = hint
191 self.hint = hint
181 # Pass the message into the Exception constructor to help extensions
192 # Pass the message into the Exception constructor to help extensions
182 # that look for exc.args[0].
193 # that look for exc.args[0].
183 Exception.__init__(self, message)
194 Exception.__init__(self, message)
184
195
185 def __bytes__(self):
196 def __bytes__(self):
186 return self.message
197 return self.message
187
198
188 if pycompat.ispy3:
199 if pycompat.ispy3:
189
200
190 def __str__(self):
201 def __str__(self):
191 # the output would be unreadable if the message was translated,
202 # the output would be unreadable if the message was translated,
192 # but do not replace it with encoding.strfromlocal(), which
203 # but do not replace it with encoding.strfromlocal(), which
193 # may raise another exception.
204 # may raise another exception.
194 return pycompat.sysstr(self.__bytes__())
205 return pycompat.sysstr(self.__bytes__())
195
206
196 def format(self):
207 def format(self):
208 # type: () -> bytes
197 from .i18n import _
209 from .i18n import _
198
210
199 message = _(b"abort: %s\n") % self.message
211 message = _(b"abort: %s\n") % self.message
200 if self.hint:
212 if self.hint:
201 message += _(b"(%s)\n") % self.hint
213 message += _(b"(%s)\n") % self.hint
202 return message
214 return message
203
215
204
216
205 class InputError(Abort):
217 class InputError(Abort):
206 """Indicates that the user made an error in their input.
218 """Indicates that the user made an error in their input.
207
219
208 Examples: Invalid command, invalid flags, invalid revision.
220 Examples: Invalid command, invalid flags, invalid revision.
209 """
221 """
210
222
211
223
212 class StateError(Abort):
224 class StateError(Abort):
213 """Indicates that the operation might work if retried in a different state.
225 """Indicates that the operation might work if retried in a different state.
214
226
215 Examples: Unresolved merge conflicts, unfinished operations.
227 Examples: Unresolved merge conflicts, unfinished operations.
216 """
228 """
217
229
218
230
219 class CanceledError(Abort):
231 class CanceledError(Abort):
220 """Indicates that the user canceled the operation.
232 """Indicates that the user canceled the operation.
221
233
222 Examples: Close commit editor with error status, quit chistedit.
234 Examples: Close commit editor with error status, quit chistedit.
223 """
235 """
224
236
225
237
226 class SecurityError(Abort):
238 class SecurityError(Abort):
227 """Indicates that some aspect of security failed.
239 """Indicates that some aspect of security failed.
228
240
229 Examples: Bad server credentials, expired local credentials for network
241 Examples: Bad server credentials, expired local credentials for network
230 filesystem, mismatched GPG signature, DoS protection.
242 filesystem, mismatched GPG signature, DoS protection.
231 """
243 """
232
244
233
245
234 class HookLoadError(Abort):
246 class HookLoadError(Abort):
235 """raised when loading a hook fails, aborting an operation
247 """raised when loading a hook fails, aborting an operation
236
248
237 Exists to allow more specialized catching."""
249 Exists to allow more specialized catching."""
238
250
239
251
240 class HookAbort(Abort):
252 class HookAbort(Abort):
241 """raised when a validation hook fails, aborting an operation
253 """raised when a validation hook fails, aborting an operation
242
254
243 Exists to allow more specialized catching."""
255 Exists to allow more specialized catching."""
244
256
245
257
246 class ConfigError(Abort):
258 class ConfigError(Abort):
247 """Exception raised when parsing config files"""
259 """Exception raised when parsing config files"""
248
260
249 def __init__(self, message, location=None, hint=None):
261 def __init__(self, message, location=None, hint=None):
262 # type: (bytes, Optional[bytes], Optional[bytes]) -> None
250 super(ConfigError, self).__init__(message, hint=hint)
263 super(ConfigError, self).__init__(message, hint=hint)
251 self.location = location
264 self.location = location
252
265
253 def format(self):
266 def format(self):
267 # type: () -> bytes
254 from .i18n import _
268 from .i18n import _
255
269
256 if self.location is not None:
270 if self.location is not None:
257 message = _(b"config error at %s: %s\n") % (
271 message = _(b"config error at %s: %s\n") % (
258 pycompat.bytestr(self.location),
272 pycompat.bytestr(self.location),
259 self.message,
273 self.message,
260 )
274 )
261 else:
275 else:
262 message = _(b"config error: %s\n") % self.message
276 message = _(b"config error: %s\n") % self.message
263 if self.hint:
277 if self.hint:
264 message += _(b"(%s)\n") % self.hint
278 message += _(b"(%s)\n") % self.hint
265 return message
279 return message
266
280
267
281
268 class UpdateAbort(Abort):
282 class UpdateAbort(Abort):
269 """Raised when an update is aborted for destination issue"""
283 """Raised when an update is aborted for destination issue"""
270
284
271
285
272 class MergeDestAbort(Abort):
286 class MergeDestAbort(Abort):
273 """Raised when an update is aborted for destination issues"""
287 """Raised when an update is aborted for destination issues"""
274
288
275
289
276 class NoMergeDestAbort(MergeDestAbort):
290 class NoMergeDestAbort(MergeDestAbort):
277 """Raised when an update is aborted because there is nothing to merge"""
291 """Raised when an update is aborted because there is nothing to merge"""
278
292
279
293
280 class ManyMergeDestAbort(MergeDestAbort):
294 class ManyMergeDestAbort(MergeDestAbort):
281 """Raised when an update is aborted because destination is ambiguous"""
295 """Raised when an update is aborted because destination is ambiguous"""
282
296
283
297
284 class ResponseExpected(Abort):
298 class ResponseExpected(Abort):
285 """Raised when an EOF is received for a prompt"""
299 """Raised when an EOF is received for a prompt"""
286
300
287 def __init__(self):
301 def __init__(self):
288 from .i18n import _
302 from .i18n import _
289
303
290 Abort.__init__(self, _(b'response expected'))
304 Abort.__init__(self, _(b'response expected'))
291
305
292
306
293 class OutOfBandError(Hint, Exception):
307 class OutOfBandError(Hint, Exception):
294 """Exception raised when a remote repo reports failure"""
308 """Exception raised when a remote repo reports failure"""
295
309
296 __bytes__ = _tobytes
310 __bytes__ = _tobytes
297
311
298
312
299 class ParseError(Abort):
313 class ParseError(Abort):
300 """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
314 """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
301
315
302 def __init__(self, message, location=None, hint=None):
316 def __init__(self, message, location=None, hint=None):
317 # type: (bytes, Optional[Union[bytes, int]], Optional[bytes]) -> None
303 super(ParseError, self).__init__(message, hint=hint)
318 super(ParseError, self).__init__(message, hint=hint)
304 self.location = location
319 self.location = location
305
320
306 def format(self):
321 def format(self):
322 # type: () -> bytes
307 from .i18n import _
323 from .i18n import _
308
324
309 if self.location is not None:
325 if self.location is not None:
310 message = _(b"hg: parse error at %s: %s\n") % (
326 message = _(b"hg: parse error at %s: %s\n") % (
311 pycompat.bytestr(self.location),
327 pycompat.bytestr(self.location),
312 self.message,
328 self.message,
313 )
329 )
314 else:
330 else:
315 message = _(b"hg: parse error: %s\n") % self.message
331 message = _(b"hg: parse error: %s\n") % self.message
316 if self.hint:
332 if self.hint:
317 message += _(b"(%s)\n") % self.hint
333 message += _(b"(%s)\n") % self.hint
318 return message
334 return message
319
335
320
336
321 class PatchError(Exception):
337 class PatchError(Exception):
322 __bytes__ = _tobytes
338 __bytes__ = _tobytes
323
339
324
340
325 def getsimilar(symbols, value):
341 def getsimilar(symbols, value):
342 # type: (Iterable[bytes], bytes) -> List[bytes]
326 sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
343 sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
327 # The cutoff for similarity here is pretty arbitrary. It should
344 # The cutoff for similarity here is pretty arbitrary. It should
328 # probably be investigated and tweaked.
345 # probably be investigated and tweaked.
329 return [s for s in symbols if sim(s) > 0.6]
346 return [s for s in symbols if sim(s) > 0.6]
330
347
331
348
332 def similarity_hint(similar):
349 def similarity_hint(similar):
350 # type: (List[bytes]) -> Optional[bytes]
333 from .i18n import _
351 from .i18n import _
334
352
335 if len(similar) == 1:
353 if len(similar) == 1:
336 return _(b"did you mean %s?") % similar[0]
354 return _(b"did you mean %s?") % similar[0]
337 elif similar:
355 elif similar:
338 ss = b", ".join(sorted(similar))
356 ss = b", ".join(sorted(similar))
339 return _(b"did you mean one of %s?") % ss
357 return _(b"did you mean one of %s?") % ss
340 else:
358 else:
341 return None
359 return None
342
360
343
361
344 class UnknownIdentifier(ParseError):
362 class UnknownIdentifier(ParseError):
345 """Exception raised when a {rev,file}set references an unknown identifier"""
363 """Exception raised when a {rev,file}set references an unknown identifier"""
346
364
347 def __init__(self, function, symbols):
365 def __init__(self, function, symbols):
366 # type: (bytes, Iterable[bytes]) -> None
348 from .i18n import _
367 from .i18n import _
349
368
350 similar = getsimilar(symbols, function)
369 similar = getsimilar(symbols, function)
351 hint = similarity_hint(similar)
370 hint = similarity_hint(similar)
352
371
353 ParseError.__init__(
372 ParseError.__init__(
354 self, _(b"unknown identifier: %s") % function, hint=hint
373 self, _(b"unknown identifier: %s") % function, hint=hint
355 )
374 )
356
375
357
376
358 class RepoError(Hint, Exception):
377 class RepoError(Hint, Exception):
359 __bytes__ = _tobytes
378 __bytes__ = _tobytes
360
379
361
380
362 class RepoLookupError(RepoError):
381 class RepoLookupError(RepoError):
363 pass
382 pass
364
383
365
384
366 class FilteredRepoLookupError(RepoLookupError):
385 class FilteredRepoLookupError(RepoLookupError):
367 pass
386 pass
368
387
369
388
370 class CapabilityError(RepoError):
389 class CapabilityError(RepoError):
371 pass
390 pass
372
391
373
392
374 class RequirementError(RepoError):
393 class RequirementError(RepoError):
375 """Exception raised if .hg/requires has an unknown entry."""
394 """Exception raised if .hg/requires has an unknown entry."""
376
395
377
396
378 class StdioError(IOError):
397 class StdioError(IOError):
379 """Raised if I/O to stdout or stderr fails"""
398 """Raised if I/O to stdout or stderr fails"""
380
399
381 def __init__(self, err):
400 def __init__(self, err):
401 # type: (IOError) -> None
382 IOError.__init__(self, err.errno, err.strerror)
402 IOError.__init__(self, err.errno, err.strerror)
383
403
384 # no __bytes__() because error message is derived from the standard IOError
404 # no __bytes__() because error message is derived from the standard IOError
385
405
386
406
387 class UnsupportedMergeRecords(Abort):
407 class UnsupportedMergeRecords(Abort):
388 def __init__(self, recordtypes):
408 def __init__(self, recordtypes):
409 # type: (Iterable[bytes]) -> None
389 from .i18n import _
410 from .i18n import _
390
411
391 self.recordtypes = sorted(recordtypes)
412 self.recordtypes = sorted(recordtypes)
392 s = b' '.join(self.recordtypes)
413 s = b' '.join(self.recordtypes)
393 Abort.__init__(
414 Abort.__init__(
394 self,
415 self,
395 _(b'unsupported merge state records: %s') % s,
416 _(b'unsupported merge state records: %s') % s,
396 hint=_(
417 hint=_(
397 b'see https://mercurial-scm.org/wiki/MergeStateRecords for '
418 b'see https://mercurial-scm.org/wiki/MergeStateRecords for '
398 b'more information'
419 b'more information'
399 ),
420 ),
400 )
421 )
401
422
402
423
403 class UnknownVersion(Abort):
424 class UnknownVersion(Abort):
404 """generic exception for aborting from an encounter with an unknown version"""
425 """generic exception for aborting from an encounter with an unknown version"""
405
426
406 def __init__(self, msg, hint=None, version=None):
427 def __init__(self, msg, hint=None, version=None):
428 # type: (bytes, Optional[bytes], Optional[bytes]) -> None
407 self.version = version
429 self.version = version
408 super(UnknownVersion, self).__init__(msg, hint=hint)
430 super(UnknownVersion, self).__init__(msg, hint=hint)
409
431
410
432
411 class LockError(IOError):
433 class LockError(IOError):
412 def __init__(self, errno, strerror, filename, desc):
434 def __init__(self, errno, strerror, filename, desc):
435 # TODO: figure out if this should be bytes or str
436 # _type: (int, str, str, bytes) -> None
413 IOError.__init__(self, errno, strerror, filename)
437 IOError.__init__(self, errno, strerror, filename)
414 self.desc = desc
438 self.desc = desc
415
439
416 # no __bytes__() because error message is derived from the standard IOError
440 # no __bytes__() because error message is derived from the standard IOError
417
441
418
442
419 class LockHeld(LockError):
443 class LockHeld(LockError):
420 def __init__(self, errno, filename, desc, locker):
444 def __init__(self, errno, filename, desc, locker):
421 LockError.__init__(self, errno, b'Lock held', filename, desc)
445 LockError.__init__(self, errno, b'Lock held', filename, desc)
422 self.locker = locker
446 self.locker = locker
423
447
424
448
425 class LockUnavailable(LockError):
449 class LockUnavailable(LockError):
426 pass
450 pass
427
451
428
452
429 # LockError is for errors while acquiring the lock -- this is unrelated
453 # LockError is for errors while acquiring the lock -- this is unrelated
430 class LockInheritanceContractViolation(RuntimeError):
454 class LockInheritanceContractViolation(RuntimeError):
431 __bytes__ = _tobytes
455 __bytes__ = _tobytes
432
456
433
457
434 class ResponseError(Exception):
458 class ResponseError(Exception):
435 """Raised to print an error with part of output and exit."""
459 """Raised to print an error with part of output and exit."""
436
460
437 __bytes__ = _tobytes
461 __bytes__ = _tobytes
438
462
439
463
440 # derived from KeyboardInterrupt to simplify some breakout code
464 # derived from KeyboardInterrupt to simplify some breakout code
441 class SignalInterrupt(KeyboardInterrupt):
465 class SignalInterrupt(KeyboardInterrupt):
442 """Exception raised on SIGTERM and SIGHUP."""
466 """Exception raised on SIGTERM and SIGHUP."""
443
467
444
468
445 class SignatureError(Exception):
469 class SignatureError(Exception):
446 __bytes__ = _tobytes
470 __bytes__ = _tobytes
447
471
448
472
449 class PushRaced(RuntimeError):
473 class PushRaced(RuntimeError):
450 """An exception raised during unbundling that indicate a push race"""
474 """An exception raised during unbundling that indicate a push race"""
451
475
452 __bytes__ = _tobytes
476 __bytes__ = _tobytes
453
477
454
478
455 class ProgrammingError(Hint, RuntimeError):
479 class ProgrammingError(Hint, RuntimeError):
456 """Raised if a mercurial (core or extension) developer made a mistake"""
480 """Raised if a mercurial (core or extension) developer made a mistake"""
457
481
458 def __init__(self, msg, *args, **kwargs):
482 def __init__(self, msg, *args, **kwargs):
483 # type: (AnyStr, Any, Any) -> None
459 # On Python 3, turn the message back into a string since this is
484 # On Python 3, turn the message back into a string since this is
460 # an internal-only error that won't be printed except in a
485 # an internal-only error that won't be printed except in a
461 # stack traces.
486 # stack traces.
462 msg = pycompat.sysstr(msg)
487 msg = pycompat.sysstr(msg)
463 super(ProgrammingError, self).__init__(msg, *args, **kwargs)
488 super(ProgrammingError, self).__init__(msg, *args, **kwargs)
464
489
465 __bytes__ = _tobytes
490 __bytes__ = _tobytes
466
491
467
492
468 class WdirUnsupported(Exception):
493 class WdirUnsupported(Exception):
469 """An exception which is raised when 'wdir()' is not supported"""
494 """An exception which is raised when 'wdir()' is not supported"""
470
495
471 __bytes__ = _tobytes
496 __bytes__ = _tobytes
472
497
473
498
474 # bundle2 related errors
499 # bundle2 related errors
475 class BundleValueError(ValueError):
500 class BundleValueError(ValueError):
476 """error raised when bundle2 cannot be processed"""
501 """error raised when bundle2 cannot be processed"""
477
502
478 __bytes__ = _tobytes
503 __bytes__ = _tobytes
479
504
480
505
481 class BundleUnknownFeatureError(BundleValueError):
506 class BundleUnknownFeatureError(BundleValueError):
482 def __init__(self, parttype=None, params=(), values=()):
507 def __init__(self, parttype=None, params=(), values=()):
483 self.parttype = parttype
508 self.parttype = parttype
484 self.params = params
509 self.params = params
485 self.values = values
510 self.values = values
486 if self.parttype is None:
511 if self.parttype is None:
487 msg = b'Stream Parameter'
512 msg = b'Stream Parameter'
488 else:
513 else:
489 msg = parttype
514 msg = parttype
490 entries = self.params
515 entries = self.params
491 if self.params and self.values:
516 if self.params and self.values:
492 assert len(self.params) == len(self.values)
517 assert len(self.params) == len(self.values)
493 entries = []
518 entries = []
494 for idx, par in enumerate(self.params):
519 for idx, par in enumerate(self.params):
495 val = self.values[idx]
520 val = self.values[idx]
496 if val is None:
521 if val is None:
497 entries.append(val)
522 entries.append(val)
498 else:
523 else:
499 entries.append(b"%s=%r" % (par, pycompat.maybebytestr(val)))
524 entries.append(b"%s=%r" % (par, pycompat.maybebytestr(val)))
500 if entries:
525 if entries:
501 msg = b'%s - %s' % (msg, b', '.join(entries))
526 msg = b'%s - %s' % (msg, b', '.join(entries))
502 ValueError.__init__(self, msg)
527 ValueError.__init__(self, msg) # TODO: convert to str?
503
528
504
529
505 class ReadOnlyPartError(RuntimeError):
530 class ReadOnlyPartError(RuntimeError):
506 """error raised when code tries to alter a part being generated"""
531 """error raised when code tries to alter a part being generated"""
507
532
508 __bytes__ = _tobytes
533 __bytes__ = _tobytes
509
534
510
535
511 class PushkeyFailed(Abort):
536 class PushkeyFailed(Abort):
512 """error raised when a pushkey part failed to update a value"""
537 """error raised when a pushkey part failed to update a value"""
513
538
514 def __init__(
539 def __init__(
515 self, partid, namespace=None, key=None, new=None, old=None, ret=None
540 self, partid, namespace=None, key=None, new=None, old=None, ret=None
516 ):
541 ):
517 self.partid = partid
542 self.partid = partid
518 self.namespace = namespace
543 self.namespace = namespace
519 self.key = key
544 self.key = key
520 self.new = new
545 self.new = new
521 self.old = old
546 self.old = old
522 self.ret = ret
547 self.ret = ret
523 # no i18n expected to be processed into a better message
548 # no i18n expected to be processed into a better message
524 Abort.__init__(
549 Abort.__init__(
525 self, b'failed to update value for "%s/%s"' % (namespace, key)
550 self, b'failed to update value for "%s/%s"' % (namespace, key)
526 )
551 )
527
552
528
553
529 class CensoredNodeError(StorageError):
554 class CensoredNodeError(StorageError):
530 """error raised when content verification fails on a censored node
555 """error raised when content verification fails on a censored node
531
556
532 Also contains the tombstone data substituted for the uncensored data.
557 Also contains the tombstone data substituted for the uncensored data.
533 """
558 """
534
559
535 def __init__(self, filename, node, tombstone):
560 def __init__(self, filename, node, tombstone):
561 # type: (bytes, bytes, bytes) -> None
536 from .node import short
562 from .node import short
537
563
538 StorageError.__init__(self, b'%s:%s' % (filename, short(node)))
564 StorageError.__init__(self, b'%s:%s' % (filename, short(node)))
539 self.tombstone = tombstone
565 self.tombstone = tombstone
540
566
541
567
542 class CensoredBaseError(StorageError):
568 class CensoredBaseError(StorageError):
543 """error raised when a delta is rejected because its base is censored
569 """error raised when a delta is rejected because its base is censored
544
570
545 A delta based on a censored revision must be formed as single patch
571 A delta based on a censored revision must be formed as single patch
546 operation which replaces the entire base with new content. This ensures
572 operation which replaces the entire base with new content. This ensures
547 the delta may be applied by clones which have not censored the base.
573 the delta may be applied by clones which have not censored the base.
548 """
574 """
549
575
550
576
551 class InvalidBundleSpecification(Exception):
577 class InvalidBundleSpecification(Exception):
552 """error raised when a bundle specification is invalid.
578 """error raised when a bundle specification is invalid.
553
579
554 This is used for syntax errors as opposed to support errors.
580 This is used for syntax errors as opposed to support errors.
555 """
581 """
556
582
557 __bytes__ = _tobytes
583 __bytes__ = _tobytes
558
584
559
585
560 class UnsupportedBundleSpecification(Exception):
586 class UnsupportedBundleSpecification(Exception):
561 """error raised when a bundle specification is not supported."""
587 """error raised when a bundle specification is not supported."""
562
588
563 __bytes__ = _tobytes
589 __bytes__ = _tobytes
564
590
565
591
566 class CorruptedState(Exception):
592 class CorruptedState(Exception):
567 """error raised when a command is not able to read its state from file"""
593 """error raised when a command is not able to read its state from file"""
568
594
569 __bytes__ = _tobytes
595 __bytes__ = _tobytes
570
596
571
597
572 class PeerTransportError(Abort):
598 class PeerTransportError(Abort):
573 """Transport-level I/O error when communicating with a peer repo."""
599 """Transport-level I/O error when communicating with a peer repo."""
574
600
575
601
576 class InMemoryMergeConflictsError(Exception):
602 class InMemoryMergeConflictsError(Exception):
577 """Exception raised when merge conflicts arose during an in-memory merge."""
603 """Exception raised when merge conflicts arose during an in-memory merge."""
578
604
579 __bytes__ = _tobytes
605 __bytes__ = _tobytes
580
606
581
607
582 class WireprotoCommandError(Exception):
608 class WireprotoCommandError(Exception):
583 """Represents an error during execution of a wire protocol command.
609 """Represents an error during execution of a wire protocol command.
584
610
585 Should only be thrown by wire protocol version 2 commands.
611 Should only be thrown by wire protocol version 2 commands.
586
612
587 The error is a formatter string and an optional iterable of arguments.
613 The error is a formatter string and an optional iterable of arguments.
588 """
614 """
589
615
590 def __init__(self, message, args=None):
616 def __init__(self, message, args=None):
617 # type: (bytes, Optional[Sequence[bytes]]) -> None
591 self.message = message
618 self.message = message
592 self.messageargs = args
619 self.messageargs = args
General Comments 0
You need to be logged in to leave comments. Login now