~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/errors.py

  • Committer: Martin Pool
  • Date: 2006-06-15 05:36:34 UTC
  • mto: This revision was merged to the branch mainline in revision 1797.
  • Revision ID: mbp@sourcefrog.net-20060615053634-4fd52ba691855659
Clean up many exception classes.

Errors indicating a user error are now shown with is_user_error on the
exception; use this rather than hardcoding a list of exceptions that should be
handled this way.

Exceptions now inherit from BzrNewException where possible to use consistent
formatting method.

Remove rather obsolete docstring test on Branch.missing_revisions.

Remove dead code from find_merge_base.


Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Exceptions for bzr, and reporting of them.
18
18
 
 
19
There are 3 different classes of error:
 
20
 
 
21
 * KeyboardInterrupt, and OSError with EPIPE - the program terminates 
 
22
   with an appropriate short message
 
23
 
 
24
 * User errors, indicating a problem caused by the user such as a bad URL.
 
25
   These are printed in a short form.
 
26
 
 
27
 * Internal unexpected errors, including most Python builtin errors
 
28
   and some raised from inside bzr.  These are printed with a full 
 
29
   traceback and an invitation to report the bug.
 
30
 
19
31
Exceptions are caught at a high level to report errors to the user, and
20
32
might also be caught inside the program.  Therefore it needs to be
21
33
possible to convert them to a meaningful string, and also for them to be
44
56
Therefore:
45
57
 
46
58
 * create a new exception class for any class of error that can be
47
 
   usefully distinguished.
48
 
 
49
 
 * the printable form of an exception is generated by the base class
50
 
   __str__ method
51
 
 
52
 
Exception strings should start with a capital letter and not have a final
53
 
fullstop.
 
59
   usefully distinguished.  If no callers are likely to want to catch
 
60
   one but not another, don't worry about them.
 
61
 
 
62
 * the __str__ method should generate something useful; BzrError provides
 
63
   a good default implementation
 
64
 
 
65
Exception strings should start with a capital letter and should not have a
 
66
final fullstop.
54
67
"""
55
68
 
56
69
from warnings import warn
81
94
 
82
95
 
83
96
class BzrError(StandardError):
 
97
    
 
98
    is_user_error = True
 
99
    
84
100
    def __str__(self):
85
101
        # XXX: Should we show the exception class in 
86
102
        # exceptions that don't provide their own message?  
119
135
class BzrCheckError(BzrNewError):
120
136
    """Internal check failed: %(message)s"""
121
137
 
 
138
    is_user_error = False
 
139
 
122
140
    def __init__(self, message):
123
141
        BzrNewError.__init__(self)
124
142
        self.message = message
126
144
 
127
145
class InvalidEntryName(BzrNewError):
128
146
    """Invalid entry name: %(name)s"""
 
147
 
 
148
    is_user_error = False
 
149
 
129
150
    def __init__(self, name):
130
151
        BzrNewError.__init__(self)
131
152
        self.name = name
163
184
        self.url = url
164
185
 
165
186
 
166
 
class BzrCommandError(BzrError):
 
187
class BzrCommandError(BzrNewError):
 
188
    """Error from user command"""
 
189
    is_user_error = True
167
190
    # Error from malformed user command
168
191
    # This is being misused as a generic exception
169
192
    # pleae subclass. RBC 20051030
172
195
    # are not intended to be caught anyway.  UI code need not subclass
173
196
    # BzrCommandError, and non-UI code should not throw a subclass of
174
197
    # BzrCommandError.  ADHB 20051211
 
198
    def __init__(self, msg):
 
199
        self.msg = msg
 
200
 
175
201
    def __str__(self):
176
 
        return self.args[0]
177
 
 
178
 
 
179
 
class BzrOptionError(BzrCommandError):
180
 
    """Some missing or otherwise incorrect option was supplied."""
181
 
 
182
 
    
183
 
class StrictCommitFailed(Exception):
 
202
        return self.msg
 
203
 
 
204
 
 
205
class StrictCommitFailed(BzrNewError):
184
206
    """Commit refused because there are unknowns in the tree."""
185
207
 
186
208
 
199
221
 
200
222
 
201
223
class NoSuchFile(PathError):
202
 
    """No such file: %(path)r%(extra)s"""
 
224
    """No such file: %(path)s%(extra)s"""
203
225
 
204
226
 
205
227
class FileExists(PathError):
206
 
    """File exists: %(path)r%(extra)s"""
 
228
    """File exists: %(path)s%(extra)s"""
207
229
 
208
230
 
209
231
class DirectoryNotEmpty(PathError):
210
 
    """Directory not empty: %(path)r%(extra)s"""
 
232
    """Directory not empty: %(path)s%(extra)s"""
211
233
 
212
234
 
213
235
class ResourceBusy(PathError):
214
 
    """Device or resource busy: %(path)r%(extra)s"""
 
236
    """Device or resource busy: %(path)s%(extra)s"""
215
237
 
216
238
 
217
239
class PermissionDenied(PathError):
218
 
    """Permission denied: %(path)r%(extra)s"""
 
240
    """Permission denied: %(path)s%(extra)s"""
219
241
 
220
242
 
221
243
class PathNotChild(BzrNewError):
222
 
    """Path %(path)r is not a child of path %(base)r%(extra)s"""
 
244
    """Path %(path)s is not a child of path %(base)s%(extra)s"""
 
245
 
 
246
    is_user_error = False
 
247
 
223
248
    def __init__(self, path, base, extra=None):
224
249
        BzrNewError.__init__(self)
225
250
        self.path = path
244
269
 
245
270
 
246
271
class NoRepositoryPresent(BzrNewError):
247
 
    """No repository present: %(path)r"""
 
272
    """No repository present: %(path)s"""
248
273
    def __init__(self, bzrdir):
249
274
        BzrNewError.__init__(self)
250
275
        self.path = bzrdir.transport.clone('..').base
260
285
        self.path = path
261
286
 
262
287
 
263
 
class UnsupportedFormatError(BzrError):
264
 
    """Specified path is a bzr branch that we recognize but cannot read."""
265
 
    def __str__(self):
266
 
        return 'unsupported branch format: %s' % self.args[0]
267
 
 
268
 
 
269
 
class UnknownFormatError(BzrError):
270
 
    """Specified path is a bzr branch whose format we do not recognize."""
271
 
    def __str__(self):
272
 
        return 'unknown branch format: %s' % self.args[0]
 
288
class UnsupportedFormatError(BzrNewError):
 
289
    """Unsupported branch format: %(format)s"""
 
290
 
 
291
 
 
292
class UnknownFormatError(BzrNewError):
 
293
    """Unknown branch format: %(format)s"""
273
294
 
274
295
 
275
296
class IncompatibleFormat(BzrNewError):
357
378
 
358
379
 
359
380
class ObjectNotLocked(LockError):
360
 
    """%(obj)r is not locked"""
 
381
    """%(obj)s is not locked"""
 
382
    is_user_error = False
361
383
    # this can indicate that any particular object is not locked; see also
362
384
    # LockNotHeld which means that a particular *lock* object is not held by
363
385
    # the caller -- perhaps they should be unified.
366
388
 
367
389
 
368
390
class ReadOnlyObjectDirtiedError(ReadOnlyError):
369
 
    """Cannot change object %(obj)r in read only transaction"""
 
391
    """Cannot change object %(obj)s in read only transaction"""
370
392
    def __init__(self, obj):
371
393
        self.obj = obj
372
394
 
391
413
 
392
414
 
393
415
class LockBreakMismatch(LockError):
394
 
    """Lock was released and re-acquired before being broken: %(lock)s: held by %(holder)r, wanted to break %(target)r"""
 
416
    """Lock was released and re-acquired before being broken: %(lock)s: held by %(holder)s, wanted to break %(target)r"""
395
417
    def __init__(self, lock, holder, target):
396
418
        self.lock = lock
397
419
        self.holder = holder
425
447
    """Commit refused because there are unknowns in the tree."""
426
448
 
427
449
 
428
 
class NoSuchRevision(BzrError):
 
450
class NoSuchRevision(BzrNewError):
 
451
    """Branch %(branch)s has no revision %(revision)s"""
 
452
 
 
453
    is_user_error = False
 
454
 
429
455
    def __init__(self, branch, revision):
430
456
        self.branch = branch
431
457
        self.revision = revision
432
 
        msg = "Branch %s has no revision %s" % (branch, revision)
433
 
        BzrError.__init__(self, msg)
434
 
 
435
 
 
436
 
class HistoryMissing(BzrError):
437
 
    def __init__(self, branch, object_type, object_id):
438
 
        self.branch = branch
439
 
        BzrError.__init__(self,
440
 
                          '%s is missing %s {%s}'
441
 
                          % (branch, object_type, object_id))
442
 
 
443
 
 
444
 
class DivergedBranches(BzrError):
 
458
 
 
459
 
 
460
class DivergedBranches(BzrNewError):
 
461
    "These branches have diverged.  Use the merge command to reconcile them."""
 
462
 
 
463
    is_user_error = True
445
464
 
446
465
    def __init__(self, branch1, branch2):
447
 
        BzrError.__init__(self, "These branches have diverged.  Try merge.")
448
466
        self.branch1 = branch1
449
467
        self.branch2 = branch2
450
468
 
451
469
 
452
 
class UnrelatedBranches(BzrCommandError):
453
 
    def __init__(self):
454
 
        msg = "Branches have no common ancestor, and no base revision"\
455
 
            " specified."
456
 
        BzrCommandError.__init__(self, msg)
457
 
 
458
 
 
459
 
class NoCommonAncestor(BzrError):
 
470
class UnrelatedBranches(BzrNewError):
 
471
    "Branches have no common ancestor, and no merge base revision was specified."
 
472
 
 
473
    is_user_error = True
 
474
 
 
475
 
 
476
class NoCommonAncestor(BzrNewError):
 
477
    "Revisions have no common ancestor: %(revision_a)s %(revision_b)s"
 
478
 
460
479
    def __init__(self, revision_a, revision_b):
461
 
        msg = "Revisions have no common ancestor: %s %s." \
462
 
            % (revision_a, revision_b) 
463
 
        BzrError.__init__(self, msg)
 
480
        self.revision_a = revision_a
 
481
        self.revision_b = revision_b
464
482
 
465
483
 
466
484
class NoCommonRoot(BzrError):