~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/errors.py

  • Committer: Martin Pool
  • Date: 2006-06-20 07:55:43 UTC
  • mfrom: (1798 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1799.
  • Revision ID: mbp@sourcefrog.net-20060620075543-b10f6575d4a4fa32
[merge] bzr.dev

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):
167
 
    # Error from malformed user command
168
 
    # This is being misused as a generic exception
169
 
    # pleae subclass. RBC 20051030
 
187
class BzrCommandError(BzrNewError):
 
188
    """Error from user command"""
 
189
 
 
190
    is_user_error = True
 
191
 
 
192
    # Error from malformed user command; please avoid raising this as a
 
193
    # generic exception not caused by user input.
170
194
    #
171
195
    # I think it's a waste of effort to differentiate between errors that
172
196
    # are not intended to be caught anyway.  UI code need not subclass
173
197
    # BzrCommandError, and non-UI code should not throw a subclass of
174
198
    # BzrCommandError.  ADHB 20051211
 
199
    def __init__(self, msg):
 
200
        self.msg = msg
 
201
 
175
202
    def __str__(self):
176
 
        return self.args[0]
 
203
        return self.msg
177
204
 
178
205
 
179
206
class BzrOptionError(BzrCommandError):
180
 
    """Some missing or otherwise incorrect option was supplied."""
 
207
    """Error in command line options"""
181
208
 
182
209
    
183
 
class StrictCommitFailed(Exception):
184
 
    """Commit refused because there are unknowns in the tree."""
 
210
class StrictCommitFailed(BzrNewError):
 
211
    """Commit refused because there are unknown files in the tree"""
185
212
 
186
213
 
187
214
# XXX: Should be unified with TransportError; they seem to represent the
218
245
    """Permission denied: %(path)r%(extra)s"""
219
246
 
220
247
 
 
248
class InvalidURL(PathError):
 
249
    """Invalid url supplied to transport: %(path)r%(extra)s"""
 
250
 
 
251
 
 
252
class InvalidURLJoin(PathError):
 
253
    """Invalid URL join request: %(args)s%(extra)s"""
 
254
 
 
255
    def __init__(self, msg, base, args):
 
256
        PathError.__init__(self, base, msg)
 
257
        self.args = [base]
 
258
        self.args.extend(args)
 
259
 
 
260
 
221
261
class PathNotChild(BzrNewError):
222
262
    """Path %(path)r is not a child of path %(base)r%(extra)s"""
 
263
 
 
264
    is_user_error = False
 
265
 
223
266
    def __init__(self, path, base, extra=None):
224
267
        BzrNewError.__init__(self)
225
268
        self.path = path
230
273
            self.extra = ''
231
274
 
232
275
 
 
276
# TODO: This is given a URL; we try to unescape it but doing that from inside
 
277
# the exception object is a bit undesirable.
 
278
# TODO: Probably this behavior of should be a common superclass 
233
279
class NotBranchError(PathError):
234
280
    """Not a branch: %(path)s"""
235
281
 
 
282
    def __init__(self, path):
 
283
       import bzrlib.urlutils as urlutils
 
284
       self.path = urlutils.unescape_for_display(path, 'ascii')
 
285
 
236
286
 
237
287
class AlreadyBranchError(PathError):
238
288
    """Already a branch: %(path)s."""
260
310
        self.path = path
261
311
 
262
312
 
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]
 
313
class UnsupportedFormatError(BzrNewError):
 
314
    """Unsupported branch format: %(format)s"""
 
315
 
 
316
 
 
317
class UnknownFormatError(BzrNewError):
 
318
    """Unknown branch format: %(format)r"""
273
319
 
274
320
 
275
321
class IncompatibleFormat(BzrNewError):
313
359
        self.paths_as_string = ' '.join([quotefn(p) for p in paths])
314
360
 
315
361
 
316
 
class BadFileKindError(BzrError):
317
 
    """Specified file is of a kind that cannot be added.
318
 
 
319
 
    (For example a symlink or device file.)"""
320
 
 
321
 
 
322
 
class ForbiddenFileError(BzrError):
323
 
    """Cannot operate on a file because it is a control file."""
 
362
class BadFileKindError(BzrNewError):
 
363
    """Cannot operate on %(filename)s of unsupported kind %(kind)s"""
 
364
 
 
365
 
 
366
class ForbiddenControlFileError(BzrNewError):
 
367
    """Cannot operate on %(filename)s because it is a control file"""
324
368
 
325
369
 
326
370
class LockError(BzrNewError):
358
402
 
359
403
class ObjectNotLocked(LockError):
360
404
    """%(obj)r is not locked"""
 
405
 
 
406
    is_user_error = False
 
407
 
361
408
    # this can indicate that any particular object is not locked; see also
362
409
    # LockNotHeld which means that a particular *lock* object is not held by
363
410
    # the caller -- perhaps they should be unified.
425
472
    """Commit refused because there are unknowns in the tree."""
426
473
 
427
474
 
428
 
class NoSuchRevision(BzrError):
 
475
class NoSuchRevision(BzrNewError):
 
476
    """Branch %(branch)s has no revision %(revision)s"""
 
477
 
 
478
    is_user_error = False
 
479
 
429
480
    def __init__(self, branch, revision):
430
481
        self.branch = branch
431
482
        self.revision = revision
432
 
        msg = "Branch %s has no revision %s" % (branch, revision)
433
 
        BzrError.__init__(self, msg)
434
483
 
435
484
 
436
485
class HistoryMissing(BzrError):
441
490
                          % (branch, object_type, object_id))
442
491
 
443
492
 
444
 
class DivergedBranches(BzrError):
 
493
class DivergedBranches(BzrNewError):
 
494
    "These branches have diverged.  Use the merge command to reconcile them."""
 
495
 
 
496
    is_user_error = True
445
497
 
446
498
    def __init__(self, branch1, branch2):
447
 
        BzrError.__init__(self, "These branches have diverged.  Try merge.")
448
499
        self.branch1 = branch1
449
500
        self.branch2 = branch2
450
501
 
451
502
 
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):
 
503
class UnrelatedBranches(BzrNewError):
 
504
    "Branches have no common ancestor, and no merge base revision was specified."
 
505
 
 
506
    is_user_error = True
 
507
 
 
508
 
 
509
class NoCommonAncestor(BzrNewError):
 
510
    "Revisions have no common ancestor: %(revision_a)s %(revision_b)s"
 
511
 
460
512
    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)
 
513
        self.revision_a = revision_a
 
514
        self.revision_b = revision_b
464
515
 
465
516
 
466
517
class NoCommonRoot(BzrError):
491
542
    def __init__(self, bases):
492
543
        warn("BzrError AmbiguousBase has been deprecated as of bzrlib 0.8.",
493
544
                DeprecationWarning)
494
 
        msg = "The correct base is unclear, becase %s are all equally close" %\
 
545
        msg = "The correct base is unclear, because %s are all equally close" %\
495
546
            ", ".join(bases)
496
547
        BzrError.__init__(self, msg)
497
548
        self.bases = bases
842
893
        self.format = format
843
894
 
844
895
 
 
896
class NoDiff(BzrNewError):
 
897
    """Diff is not installed on this machine: %(msg)s"""
 
898
 
 
899
    def __init__(self, msg):
 
900
        super(NoDiff, self).__init__(msg=msg)
 
901
 
 
902
 
845
903
class NoDiff3(BzrNewError):
846
904
    """Diff3 is not installed on this machine."""
847
905
 
938
996
        self.measured = measured
939
997
 
940
998
 
 
999
class NotABundle(BzrNewError):
 
1000
    """Not a bzr revision-bundle: %(text)r"""
 
1001
 
 
1002
    def __init__(self, text):
 
1003
        self.text = text
 
1004
 
 
1005
 
941
1006
class BadBundle(Exception): pass
942
1007
 
943
1008