##// END OF EJS Templates
error: make HintException a mix-in class not derived from BaseException (API)...
Yuya Nishihara -
r29509:945b4c14 default
parent child Browse files
Show More
@@ -1,237 +1,242 b''
1 # error.py - Mercurial exceptions
1 # error.py - Mercurial exceptions
2 #
2 #
3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2008 Matt Mackall <mpm@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 # Do not import anything here, please
16 # Do not import anything here, please
17
17
18 class HintException(Exception):
18 class Hint(object):
19 """Mix-in to provide a hint of an error
20
21 This should come first in the inheritance list to consume **kw and pass
22 only *args to the exception class.
23 """
19 def __init__(self, *args, **kw):
24 def __init__(self, *args, **kw):
20 Exception.__init__(self, *args)
25 super(Hint, self).__init__(*args)
21 self.hint = kw.get('hint')
26 self.hint = kw.get('hint')
22
27
23 class RevlogError(HintException):
28 class RevlogError(Hint, Exception):
24 pass
29 pass
25
30
26 class FilteredIndexError(IndexError):
31 class FilteredIndexError(IndexError):
27 pass
32 pass
28
33
29 class LookupError(RevlogError, KeyError):
34 class LookupError(RevlogError, KeyError):
30 def __init__(self, name, index, message):
35 def __init__(self, name, index, message):
31 self.name = name
36 self.name = name
32 self.index = index
37 self.index = index
33 # this can't be called 'message' because at least some installs of
38 # this can't be called 'message' because at least some installs of
34 # Python 2.6+ complain about the 'message' property being deprecated
39 # Python 2.6+ complain about the 'message' property being deprecated
35 self.lookupmessage = message
40 self.lookupmessage = message
36 if isinstance(name, str) and len(name) == 20:
41 if isinstance(name, str) and len(name) == 20:
37 from .node import short
42 from .node import short
38 name = short(name)
43 name = short(name)
39 RevlogError.__init__(self, '%s@%s: %s' % (index, name, message))
44 RevlogError.__init__(self, '%s@%s: %s' % (index, name, message))
40
45
41 def __str__(self):
46 def __str__(self):
42 return RevlogError.__str__(self)
47 return RevlogError.__str__(self)
43
48
44 class FilteredLookupError(LookupError):
49 class FilteredLookupError(LookupError):
45 pass
50 pass
46
51
47 class ManifestLookupError(LookupError):
52 class ManifestLookupError(LookupError):
48 pass
53 pass
49
54
50 class CommandError(Exception):
55 class CommandError(Exception):
51 """Exception raised on errors in parsing the command line."""
56 """Exception raised on errors in parsing the command line."""
52
57
53 class InterventionRequired(HintException):
58 class InterventionRequired(Hint, Exception):
54 """Exception raised when a command requires human intervention."""
59 """Exception raised when a command requires human intervention."""
55
60
56 class Abort(HintException):
61 class Abort(Hint, Exception):
57 """Raised if a command needs to print an error and exit."""
62 """Raised if a command needs to print an error and exit."""
58
63
59 class HookLoadError(Abort):
64 class HookLoadError(Abort):
60 """raised when loading a hook fails, aborting an operation
65 """raised when loading a hook fails, aborting an operation
61
66
62 Exists to allow more specialized catching."""
67 Exists to allow more specialized catching."""
63
68
64 class HookAbort(Abort):
69 class HookAbort(Abort):
65 """raised when a validation hook fails, aborting an operation
70 """raised when a validation hook fails, aborting an operation
66
71
67 Exists to allow more specialized catching."""
72 Exists to allow more specialized catching."""
68
73
69 class ConfigError(Abort):
74 class ConfigError(Abort):
70 """Exception raised when parsing config files"""
75 """Exception raised when parsing config files"""
71
76
72 class UpdateAbort(Abort):
77 class UpdateAbort(Abort):
73 """Raised when an update is aborted for destination issue"""
78 """Raised when an update is aborted for destination issue"""
74
79
75 class MergeDestAbort(Abort):
80 class MergeDestAbort(Abort):
76 """Raised when an update is aborted for destination issues"""
81 """Raised when an update is aborted for destination issues"""
77
82
78 class NoMergeDestAbort(MergeDestAbort):
83 class NoMergeDestAbort(MergeDestAbort):
79 """Raised when an update is aborted because there is nothing to merge"""
84 """Raised when an update is aborted because there is nothing to merge"""
80
85
81 class ManyMergeDestAbort(MergeDestAbort):
86 class ManyMergeDestAbort(MergeDestAbort):
82 """Raised when an update is aborted because destination is ambigious"""
87 """Raised when an update is aborted because destination is ambigious"""
83
88
84 class ResponseExpected(Abort):
89 class ResponseExpected(Abort):
85 """Raised when an EOF is received for a prompt"""
90 """Raised when an EOF is received for a prompt"""
86 def __init__(self):
91 def __init__(self):
87 from .i18n import _
92 from .i18n import _
88 Abort.__init__(self, _('response expected'))
93 Abort.__init__(self, _('response expected'))
89
94
90 class OutOfBandError(HintException):
95 class OutOfBandError(Hint, Exception):
91 """Exception raised when a remote repo reports failure"""
96 """Exception raised when a remote repo reports failure"""
92
97
93 class ParseError(HintException):
98 class ParseError(Hint, Exception):
94 """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
99 """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
95
100
96 class UnknownIdentifier(ParseError):
101 class UnknownIdentifier(ParseError):
97 """Exception raised when a {rev,file}set references an unknown identifier"""
102 """Exception raised when a {rev,file}set references an unknown identifier"""
98
103
99 def __init__(self, function, symbols):
104 def __init__(self, function, symbols):
100 from .i18n import _
105 from .i18n import _
101 ParseError.__init__(self, _("unknown identifier: %s") % function)
106 ParseError.__init__(self, _("unknown identifier: %s") % function)
102 self.function = function
107 self.function = function
103 self.symbols = symbols
108 self.symbols = symbols
104
109
105 class RepoError(HintException):
110 class RepoError(Hint, Exception):
106 pass
111 pass
107
112
108 class RepoLookupError(RepoError):
113 class RepoLookupError(RepoError):
109 pass
114 pass
110
115
111 class FilteredRepoLookupError(RepoLookupError):
116 class FilteredRepoLookupError(RepoLookupError):
112 pass
117 pass
113
118
114 class CapabilityError(RepoError):
119 class CapabilityError(RepoError):
115 pass
120 pass
116
121
117 class RequirementError(RepoError):
122 class RequirementError(RepoError):
118 """Exception raised if .hg/requires has an unknown entry."""
123 """Exception raised if .hg/requires has an unknown entry."""
119
124
120 class UnsupportedMergeRecords(Abort):
125 class UnsupportedMergeRecords(Abort):
121 def __init__(self, recordtypes):
126 def __init__(self, recordtypes):
122 from .i18n import _
127 from .i18n import _
123 self.recordtypes = sorted(recordtypes)
128 self.recordtypes = sorted(recordtypes)
124 s = ' '.join(self.recordtypes)
129 s = ' '.join(self.recordtypes)
125 Abort.__init__(
130 Abort.__init__(
126 self, _('unsupported merge state records: %s') % s,
131 self, _('unsupported merge state records: %s') % s,
127 hint=_('see https://mercurial-scm.org/wiki/MergeStateRecords for '
132 hint=_('see https://mercurial-scm.org/wiki/MergeStateRecords for '
128 'more information'))
133 'more information'))
129
134
130 class LockError(IOError):
135 class LockError(IOError):
131 def __init__(self, errno, strerror, filename, desc):
136 def __init__(self, errno, strerror, filename, desc):
132 IOError.__init__(self, errno, strerror, filename)
137 IOError.__init__(self, errno, strerror, filename)
133 self.desc = desc
138 self.desc = desc
134
139
135 class LockHeld(LockError):
140 class LockHeld(LockError):
136 def __init__(self, errno, filename, desc, locker):
141 def __init__(self, errno, filename, desc, locker):
137 LockError.__init__(self, errno, 'Lock held', filename, desc)
142 LockError.__init__(self, errno, 'Lock held', filename, desc)
138 self.locker = locker
143 self.locker = locker
139
144
140 class LockUnavailable(LockError):
145 class LockUnavailable(LockError):
141 pass
146 pass
142
147
143 # LockError is for errors while acquiring the lock -- this is unrelated
148 # LockError is for errors while acquiring the lock -- this is unrelated
144 class LockInheritanceContractViolation(RuntimeError):
149 class LockInheritanceContractViolation(RuntimeError):
145 pass
150 pass
146
151
147 class ResponseError(Exception):
152 class ResponseError(Exception):
148 """Raised to print an error with part of output and exit."""
153 """Raised to print an error with part of output and exit."""
149
154
150 class UnknownCommand(Exception):
155 class UnknownCommand(Exception):
151 """Exception raised if command is not in the command table."""
156 """Exception raised if command is not in the command table."""
152
157
153 class AmbiguousCommand(Exception):
158 class AmbiguousCommand(Exception):
154 """Exception raised if command shortcut matches more than one command."""
159 """Exception raised if command shortcut matches more than one command."""
155
160
156 # derived from KeyboardInterrupt to simplify some breakout code
161 # derived from KeyboardInterrupt to simplify some breakout code
157 class SignalInterrupt(KeyboardInterrupt):
162 class SignalInterrupt(KeyboardInterrupt):
158 """Exception raised on SIGTERM and SIGHUP."""
163 """Exception raised on SIGTERM and SIGHUP."""
159
164
160 class SignatureError(Exception):
165 class SignatureError(Exception):
161 pass
166 pass
162
167
163 class PushRaced(RuntimeError):
168 class PushRaced(RuntimeError):
164 """An exception raised during unbundling that indicate a push race"""
169 """An exception raised during unbundling that indicate a push race"""
165
170
166 # bundle2 related errors
171 # bundle2 related errors
167 class BundleValueError(ValueError):
172 class BundleValueError(ValueError):
168 """error raised when bundle2 cannot be processed"""
173 """error raised when bundle2 cannot be processed"""
169
174
170 class BundleUnknownFeatureError(BundleValueError):
175 class BundleUnknownFeatureError(BundleValueError):
171 def __init__(self, parttype=None, params=(), values=()):
176 def __init__(self, parttype=None, params=(), values=()):
172 self.parttype = parttype
177 self.parttype = parttype
173 self.params = params
178 self.params = params
174 self.values = values
179 self.values = values
175 if self.parttype is None:
180 if self.parttype is None:
176 msg = 'Stream Parameter'
181 msg = 'Stream Parameter'
177 else:
182 else:
178 msg = parttype
183 msg = parttype
179 entries = self.params
184 entries = self.params
180 if self.params and self.values:
185 if self.params and self.values:
181 assert len(self.params) == len(self.values)
186 assert len(self.params) == len(self.values)
182 entries = []
187 entries = []
183 for idx, par in enumerate(self.params):
188 for idx, par in enumerate(self.params):
184 val = self.values[idx]
189 val = self.values[idx]
185 if val is None:
190 if val is None:
186 entries.append(val)
191 entries.append(val)
187 else:
192 else:
188 entries.append("%s=%r" % (par, val))
193 entries.append("%s=%r" % (par, val))
189 if entries:
194 if entries:
190 msg = '%s - %s' % (msg, ', '.join(entries))
195 msg = '%s - %s' % (msg, ', '.join(entries))
191 ValueError.__init__(self, msg)
196 ValueError.__init__(self, msg)
192
197
193 class ReadOnlyPartError(RuntimeError):
198 class ReadOnlyPartError(RuntimeError):
194 """error raised when code tries to alter a part being generated"""
199 """error raised when code tries to alter a part being generated"""
195
200
196 class PushkeyFailed(Abort):
201 class PushkeyFailed(Abort):
197 """error raised when a pushkey part failed to update a value"""
202 """error raised when a pushkey part failed to update a value"""
198
203
199 def __init__(self, partid, namespace=None, key=None, new=None, old=None,
204 def __init__(self, partid, namespace=None, key=None, new=None, old=None,
200 ret=None):
205 ret=None):
201 self.partid = partid
206 self.partid = partid
202 self.namespace = namespace
207 self.namespace = namespace
203 self.key = key
208 self.key = key
204 self.new = new
209 self.new = new
205 self.old = old
210 self.old = old
206 self.ret = ret
211 self.ret = ret
207 # no i18n expected to be processed into a better message
212 # no i18n expected to be processed into a better message
208 Abort.__init__(self, 'failed to update value for "%s/%s"'
213 Abort.__init__(self, 'failed to update value for "%s/%s"'
209 % (namespace, key))
214 % (namespace, key))
210
215
211 class CensoredNodeError(RevlogError):
216 class CensoredNodeError(RevlogError):
212 """error raised when content verification fails on a censored node
217 """error raised when content verification fails on a censored node
213
218
214 Also contains the tombstone data substituted for the uncensored data.
219 Also contains the tombstone data substituted for the uncensored data.
215 """
220 """
216
221
217 def __init__(self, filename, node, tombstone):
222 def __init__(self, filename, node, tombstone):
218 from .node import short
223 from .node import short
219 RevlogError.__init__(self, '%s:%s' % (filename, short(node)))
224 RevlogError.__init__(self, '%s:%s' % (filename, short(node)))
220 self.tombstone = tombstone
225 self.tombstone = tombstone
221
226
222 class CensoredBaseError(RevlogError):
227 class CensoredBaseError(RevlogError):
223 """error raised when a delta is rejected because its base is censored
228 """error raised when a delta is rejected because its base is censored
224
229
225 A delta based on a censored revision must be formed as single patch
230 A delta based on a censored revision must be formed as single patch
226 operation which replaces the entire base with new content. This ensures
231 operation which replaces the entire base with new content. This ensures
227 the delta may be applied by clones which have not censored the base.
232 the delta may be applied by clones which have not censored the base.
228 """
233 """
229
234
230 class InvalidBundleSpecification(Exception):
235 class InvalidBundleSpecification(Exception):
231 """error raised when a bundle specification is invalid.
236 """error raised when a bundle specification is invalid.
232
237
233 This is used for syntax errors as opposed to support errors.
238 This is used for syntax errors as opposed to support errors.
234 """
239 """
235
240
236 class UnsupportedBundleSpecification(Exception):
241 class UnsupportedBundleSpecification(Exception):
237 """error raised when a bundle specification is not supported."""
242 """error raised when a bundle specification is not supported."""
General Comments 0
You need to be logged in to leave comments. Login now