##// END OF EJS Templates
py3: use sysstr() to convert ProgrammingError bytes with no unicode error risk...
Yuya Nishihara -
r39632:409c42d6 default
parent child Browse files
Show More
@@ -1,331 +1,329
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 def _tobytes(exc):
20 20 """Byte-stringify exception in the same way as BaseException_str()"""
21 21 if not exc.args:
22 22 return b''
23 23 if len(exc.args) == 1:
24 24 return pycompat.bytestr(exc.args[0])
25 25 return b'(%s)' % b', '.join(b"'%s'" % pycompat.bytestr(a) for a in exc.args)
26 26
27 27 class Hint(object):
28 28 """Mix-in to provide a hint of an error
29 29
30 30 This should come first in the inheritance list to consume a hint and
31 31 pass remaining arguments to the exception class.
32 32 """
33 33 def __init__(self, *args, **kw):
34 34 self.hint = kw.pop(r'hint', None)
35 35 super(Hint, self).__init__(*args, **kw)
36 36
37 37 class RevlogError(Hint, Exception):
38 38 __bytes__ = _tobytes
39 39
40 40 class FilteredIndexError(IndexError):
41 41 __bytes__ = _tobytes
42 42
43 43 class LookupError(RevlogError, KeyError):
44 44 def __init__(self, name, index, message):
45 45 self.name = name
46 46 self.index = index
47 47 # this can't be called 'message' because at least some installs of
48 48 # Python 2.6+ complain about the 'message' property being deprecated
49 49 self.lookupmessage = message
50 50 if isinstance(name, bytes) and len(name) == 20:
51 51 from .node import short
52 52 name = short(name)
53 53 RevlogError.__init__(self, '%s@%s: %s' % (index, name, message))
54 54
55 55 def __bytes__(self):
56 56 return RevlogError.__bytes__(self)
57 57
58 58 def __str__(self):
59 59 return RevlogError.__str__(self)
60 60
61 61 class AmbiguousPrefixLookupError(LookupError):
62 62 pass
63 63
64 64 class FilteredLookupError(LookupError):
65 65 pass
66 66
67 67 class ManifestLookupError(LookupError):
68 68 pass
69 69
70 70 class CommandError(Exception):
71 71 """Exception raised on errors in parsing the command line."""
72 72 __bytes__ = _tobytes
73 73
74 74 class InterventionRequired(Hint, Exception):
75 75 """Exception raised when a command requires human intervention."""
76 76 __bytes__ = _tobytes
77 77
78 78 class Abort(Hint, Exception):
79 79 """Raised if a command needs to print an error and exit."""
80 80 __bytes__ = _tobytes
81 81
82 82 class HookLoadError(Abort):
83 83 """raised when loading a hook fails, aborting an operation
84 84
85 85 Exists to allow more specialized catching."""
86 86
87 87 class HookAbort(Abort):
88 88 """raised when a validation hook fails, aborting an operation
89 89
90 90 Exists to allow more specialized catching."""
91 91
92 92 class ConfigError(Abort):
93 93 """Exception raised when parsing config files"""
94 94
95 95 class UpdateAbort(Abort):
96 96 """Raised when an update is aborted for destination issue"""
97 97
98 98 class MergeDestAbort(Abort):
99 99 """Raised when an update is aborted for destination issues"""
100 100
101 101 class NoMergeDestAbort(MergeDestAbort):
102 102 """Raised when an update is aborted because there is nothing to merge"""
103 103
104 104 class ManyMergeDestAbort(MergeDestAbort):
105 105 """Raised when an update is aborted because destination is ambiguous"""
106 106
107 107 class ResponseExpected(Abort):
108 108 """Raised when an EOF is received for a prompt"""
109 109 def __init__(self):
110 110 from .i18n import _
111 111 Abort.__init__(self, _('response expected'))
112 112
113 113 class OutOfBandError(Hint, Exception):
114 114 """Exception raised when a remote repo reports failure"""
115 115 __bytes__ = _tobytes
116 116
117 117 class ParseError(Hint, Exception):
118 118 """Raised when parsing config files and {rev,file}sets (msg[, pos])"""
119 119 __bytes__ = _tobytes
120 120
121 121 class PatchError(Exception):
122 122 __bytes__ = _tobytes
123 123
124 124 class UnknownIdentifier(ParseError):
125 125 """Exception raised when a {rev,file}set references an unknown identifier"""
126 126
127 127 def __init__(self, function, symbols):
128 128 from .i18n import _
129 129 ParseError.__init__(self, _("unknown identifier: %s") % function)
130 130 self.function = function
131 131 self.symbols = symbols
132 132
133 133 class RepoError(Hint, Exception):
134 134 __bytes__ = _tobytes
135 135
136 136 class RepoLookupError(RepoError):
137 137 pass
138 138
139 139 class FilteredRepoLookupError(RepoLookupError):
140 140 pass
141 141
142 142 class CapabilityError(RepoError):
143 143 pass
144 144
145 145 class RequirementError(RepoError):
146 146 """Exception raised if .hg/requires has an unknown entry."""
147 147
148 148 class StdioError(IOError):
149 149 """Raised if I/O to stdout or stderr fails"""
150 150
151 151 def __init__(self, err):
152 152 IOError.__init__(self, err.errno, err.strerror)
153 153
154 154 # no __bytes__() because error message is derived from the standard IOError
155 155
156 156 class UnsupportedMergeRecords(Abort):
157 157 def __init__(self, recordtypes):
158 158 from .i18n import _
159 159 self.recordtypes = sorted(recordtypes)
160 160 s = ' '.join(self.recordtypes)
161 161 Abort.__init__(
162 162 self, _('unsupported merge state records: %s') % s,
163 163 hint=_('see https://mercurial-scm.org/wiki/MergeStateRecords for '
164 164 'more information'))
165 165
166 166 class UnknownVersion(Abort):
167 167 """generic exception for aborting from an encounter with an unknown version
168 168 """
169 169
170 170 def __init__(self, msg, hint=None, version=None):
171 171 self.version = version
172 172 super(UnknownVersion, self).__init__(msg, hint=hint)
173 173
174 174 class LockError(IOError):
175 175 def __init__(self, errno, strerror, filename, desc):
176 176 IOError.__init__(self, errno, strerror, filename)
177 177 self.desc = desc
178 178
179 179 # no __bytes__() because error message is derived from the standard IOError
180 180
181 181 class LockHeld(LockError):
182 182 def __init__(self, errno, filename, desc, locker):
183 183 LockError.__init__(self, errno, 'Lock held', filename, desc)
184 184 self.locker = locker
185 185
186 186 class LockUnavailable(LockError):
187 187 pass
188 188
189 189 # LockError is for errors while acquiring the lock -- this is unrelated
190 190 class LockInheritanceContractViolation(RuntimeError):
191 191 __bytes__ = _tobytes
192 192
193 193 class ResponseError(Exception):
194 194 """Raised to print an error with part of output and exit."""
195 195 __bytes__ = _tobytes
196 196
197 197 class UnknownCommand(Exception):
198 198 """Exception raised if command is not in the command table."""
199 199 __bytes__ = _tobytes
200 200
201 201 class AmbiguousCommand(Exception):
202 202 """Exception raised if command shortcut matches more than one command."""
203 203 __bytes__ = _tobytes
204 204
205 205 # derived from KeyboardInterrupt to simplify some breakout code
206 206 class SignalInterrupt(KeyboardInterrupt):
207 207 """Exception raised on SIGTERM and SIGHUP."""
208 208
209 209 class SignatureError(Exception):
210 210 __bytes__ = _tobytes
211 211
212 212 class PushRaced(RuntimeError):
213 213 """An exception raised during unbundling that indicate a push race"""
214 214 __bytes__ = _tobytes
215 215
216 216 class ProgrammingError(Hint, RuntimeError):
217 217 """Raised if a mercurial (core or extension) developer made a mistake"""
218 218
219 219 def __init__(self, msg, *args, **kwargs):
220 if not isinstance(msg, str):
221 # This means we're on Python 3, because we got a
222 # bytes. Turn the message back into a string since this is
223 # an internal-only error that won't be printed except in a
224 # stack traces.
225 msg = msg.decode('utf8')
220 # On Python 3, turn the message back into a string since this is
221 # an internal-only error that won't be printed except in a
222 # stack traces.
223 msg = pycompat.sysstr(msg)
226 224 super(ProgrammingError, self).__init__(msg, *args, **kwargs)
227 225
228 226 __bytes__ = _tobytes
229 227
230 228 class WdirUnsupported(Exception):
231 229 """An exception which is raised when 'wdir()' is not supported"""
232 230 __bytes__ = _tobytes
233 231
234 232 # bundle2 related errors
235 233 class BundleValueError(ValueError):
236 234 """error raised when bundle2 cannot be processed"""
237 235 __bytes__ = _tobytes
238 236
239 237 class BundleUnknownFeatureError(BundleValueError):
240 238 def __init__(self, parttype=None, params=(), values=()):
241 239 self.parttype = parttype
242 240 self.params = params
243 241 self.values = values
244 242 if self.parttype is None:
245 243 msg = 'Stream Parameter'
246 244 else:
247 245 msg = parttype
248 246 entries = self.params
249 247 if self.params and self.values:
250 248 assert len(self.params) == len(self.values)
251 249 entries = []
252 250 for idx, par in enumerate(self.params):
253 251 val = self.values[idx]
254 252 if val is None:
255 253 entries.append(val)
256 254 else:
257 255 entries.append("%s=%r" % (par, pycompat.maybebytestr(val)))
258 256 if entries:
259 257 msg = '%s - %s' % (msg, ', '.join(entries))
260 258 ValueError.__init__(self, msg)
261 259
262 260 class ReadOnlyPartError(RuntimeError):
263 261 """error raised when code tries to alter a part being generated"""
264 262 __bytes__ = _tobytes
265 263
266 264 class PushkeyFailed(Abort):
267 265 """error raised when a pushkey part failed to update a value"""
268 266
269 267 def __init__(self, partid, namespace=None, key=None, new=None, old=None,
270 268 ret=None):
271 269 self.partid = partid
272 270 self.namespace = namespace
273 271 self.key = key
274 272 self.new = new
275 273 self.old = old
276 274 self.ret = ret
277 275 # no i18n expected to be processed into a better message
278 276 Abort.__init__(self, 'failed to update value for "%s/%s"'
279 277 % (namespace, key))
280 278
281 279 class CensoredNodeError(RevlogError):
282 280 """error raised when content verification fails on a censored node
283 281
284 282 Also contains the tombstone data substituted for the uncensored data.
285 283 """
286 284
287 285 def __init__(self, filename, node, tombstone):
288 286 from .node import short
289 287 RevlogError.__init__(self, '%s:%s' % (filename, short(node)))
290 288 self.tombstone = tombstone
291 289
292 290 class CensoredBaseError(RevlogError):
293 291 """error raised when a delta is rejected because its base is censored
294 292
295 293 A delta based on a censored revision must be formed as single patch
296 294 operation which replaces the entire base with new content. This ensures
297 295 the delta may be applied by clones which have not censored the base.
298 296 """
299 297
300 298 class InvalidBundleSpecification(Exception):
301 299 """error raised when a bundle specification is invalid.
302 300
303 301 This is used for syntax errors as opposed to support errors.
304 302 """
305 303 __bytes__ = _tobytes
306 304
307 305 class UnsupportedBundleSpecification(Exception):
308 306 """error raised when a bundle specification is not supported."""
309 307 __bytes__ = _tobytes
310 308
311 309 class CorruptedState(Exception):
312 310 """error raised when a command is not able to read its state from file"""
313 311 __bytes__ = _tobytes
314 312
315 313 class PeerTransportError(Abort):
316 314 """Transport-level I/O error when communicating with a peer repo."""
317 315
318 316 class InMemoryMergeConflictsError(Exception):
319 317 """Exception raised when merge conflicts arose during an in-memory merge."""
320 318 __bytes__ = _tobytes
321 319
322 320 class WireprotoCommandError(Exception):
323 321 """Represents an error during execution of a wire protocol command.
324 322
325 323 Should only be thrown by wire protocol version 2 commands.
326 324
327 325 The error is a formatter string and an optional iterable of arguments.
328 326 """
329 327 def __init__(self, message, args=None):
330 328 self.message = message
331 329 self.messageargs = args
General Comments 0
You need to be logged in to leave comments. Login now