~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/errors.py

  • Committer: Robert Collins
  • Date: 2005-10-17 11:56:54 UTC
  • mfrom: (1185.16.59)
  • Revision ID: robertc@robertcollins.net-20051017115654-662239e1587524a8
mergeĀ fromĀ martin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# (C) 2005 Canonical
 
1
# -*- coding: UTF-8 -*-
2
2
 
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
"""Exceptions for bzr, and reporting of them.
18
 
 
19
 
Exceptions are caught at a high level to report errors to the user, and
20
 
might also be caught inside the program.  Therefore it needs to be
21
 
possible to convert them to a meaningful string, and also for them to be
22
 
interrogated by the program.
23
 
 
24
 
Exceptions are defined such that the arguments given to the constructor
25
 
are stored in the object as properties of the same name.  When the
26
 
object is printed as a string, the doc string of the class is used as
27
 
a format string with the property dictionary available to it.
28
 
 
29
 
This means that exceptions can used like this:
30
 
 
31
 
>>> import sys
32
 
>>> try:
33
 
...   raise NotBranchError(path='/foo/bar')
34
 
... except:
35
 
...   print sys.exc_type
36
 
...   print sys.exc_value
37
 
...   print sys.exc_value.path
38
 
bzrlib.errors.NotBranchError
39
 
Not a branch: /foo/bar
40
 
/foo/bar
41
 
 
42
 
Therefore:
43
 
 
44
 
 * create a new exception class for any class of error that can be
45
 
   usefully distinguished.
46
 
 
47
 
 * the printable form of an exception is generated by the base class
48
 
   __str__ method
49
 
 
50
 
Exception strings should start with a capital letter and not have a final
51
 
fullstop.
52
 
"""
53
 
 
54
 
# based on Scott James Remnant's hct error classes
55
 
 
56
 
# TODO: is there any value in providing the .args field used by standard
57
 
# python exceptions?   A list of values with no names seems less useful 
58
 
# to me.
59
 
 
60
 
# TODO: Perhaps convert the exception to a string at the moment it's 
61
 
# constructed to make sure it will succeed.  But that says nothing about
62
 
# exceptions that are never raised.
63
 
 
64
 
# TODO: Convert all the other error classes here to BzrNewError, and eliminate
65
 
# the old one.
66
 
 
67
 
 
 
17
 
 
18
__copyright__ = "Copyright (C) 2005 Canonical Ltd."
 
19
__author__ = "Martin Pool <mbp@canonical.com>"
 
20
 
 
21
# TODO: Change to a standard exception pattern: 
 
22
#
 
23
# - docstring of exceptions is a template for formatting the exception
 
24
#   so the __str__ method can be defined only in the superclass
 
25
# - the arguments to the exception are interpolated into this string
 
26
#
 
27
# when printing the exception we'd then require special handling only
 
28
# for built-in exceptions with no decent __str__ method, such as 
 
29
# ValueError and AssertionError.  See 
 
30
# scott@canonical.com--2005/hct--devel--0.10 util/errors.py
 
31
 
 
32
 
 
33
######################################################################
 
34
# exceptions 
68
35
class BzrError(StandardError):
69
36
    def __str__(self):
70
37
        # XXX: Should we show the exception class in 
84
51
            return n + `self.args`
85
52
 
86
53
 
87
 
class BzrNewError(BzrError):
88
 
    """bzr error"""
89
 
    # base classes should override the docstring with their human-
90
 
    # readable explanation
91
 
 
92
 
    def __init__(self, **kwds):
93
 
        for key, value in kwds.items():
94
 
            setattr(self, key, value)
95
 
 
 
54
class BzrCheckError(BzrError):
 
55
    pass
 
56
 
 
57
 
 
58
class InvalidRevisionNumber(BzrError):
96
59
    def __str__(self):
97
 
        try:
98
 
            return self.__doc__ % self.__dict__
99
 
        except (NameError, ValueError, KeyError), e:
100
 
            return 'Unprintable exception %s: %s' \
101
 
                % (self.__class__.__name__, str(e))
102
 
 
103
 
 
104
 
class BzrCheckError(BzrNewError):
105
 
    """Internal check failed: %(message)s"""
106
 
    def __init__(self, message):
107
 
        BzrNewError.__init__(self)
108
 
        self.message = message
109
 
 
110
 
 
111
 
class InvalidEntryName(BzrNewError):
112
 
    """Invalid entry name: %(name)s"""
113
 
    def __init__(self, name):
114
 
        BzrNewError.__init__(self)
115
 
        self.name = name
116
 
 
117
 
 
118
 
class InvalidRevisionNumber(BzrNewError):
119
 
    """Invalid revision number %(revno)d"""
120
 
    def __init__(self, revno):
121
 
        BzrNewError.__init__(self)
122
 
        self.revno = revno
123
 
 
124
 
 
125
 
class InvalidRevisionId(BzrNewError):
126
 
    """Invalid revision-id {%(revision_id)s} in %(branch)s"""
127
 
    def __init__(self, revision_id, branch):
128
 
        BzrNewError.__init__(self)
129
 
        self.revision_id = revision_id
130
 
        self.branch = branch
131
 
 
132
 
 
133
 
class NoWorkingTree(BzrNewError):
134
 
    """No WorkingTree exists for %s(base)."""
135
 
    
136
 
    def __init__(self, base):
137
 
        BzrNewError.__init__(self)
138
 
        self.base = base
 
60
        return 'invalid revision number: %r' % self.args[0]
 
61
 
 
62
 
 
63
class InvalidRevisionId(BzrError):
 
64
    pass
139
65
 
140
66
 
141
67
class BzrCommandError(BzrError):
142
68
    # Error from malformed user command
143
 
    # This is being misused as a generic exception
144
 
    # pleae subclass. RBC 20051030
145
 
    #
146
 
    # I think it's a waste of effort to differentiate between errors that
147
 
    # are not intended to be caught anyway.  UI code need not subclass
148
 
    # BzrCommandError, and non-UI code should not throw a subclass of
149
 
    # BzrCommandError.  ADHB 20051211
150
69
    def __str__(self):
151
70
        return self.args[0]
152
71
 
153
72
 
154
 
class BzrOptionError(BzrCommandError):
155
 
    """Some missing or otherwise incorrect option was supplied."""
156
 
 
157
 
    
158
 
class StrictCommitFailed(Exception):
159
 
    """Commit refused because there are unknowns in the tree."""
160
 
 
161
 
 
162
 
class PathError(BzrNewError):
163
 
    """Generic path error: %(path)r%(extra)s)"""
164
 
    def __init__(self, path, extra=None):
165
 
        BzrNewError.__init__(self)
166
 
        self.path = path
167
 
        if extra:
168
 
            self.extra = ': ' + str(extra)
169
 
        else:
170
 
            self.extra = ''
171
 
 
172
 
 
173
 
class NoSuchFile(PathError):
174
 
    """No such file: %(path)r%(extra)s"""
175
 
 
176
 
 
177
 
class FileExists(PathError):
178
 
    """File exists: %(path)r%(extra)s"""
179
 
 
180
 
 
181
 
class PermissionDenied(PathError):
182
 
    """Permission denied: %(path)r%(extra)s"""
183
 
 
184
 
 
185
 
class PathNotChild(BzrNewError):
186
 
    """Path %(path)r is not a child of path %(base)r%(extra)s"""
187
 
    def __init__(self, path, base, extra=None):
188
 
        BzrNewError.__init__(self)
189
 
        self.path = path
190
 
        self.base = base
191
 
        if extra:
192
 
            self.extra = ': ' + str(extra)
193
 
        else:
194
 
            self.extra = ''
195
 
 
196
 
 
197
 
class NotBranchError(BzrNewError):
198
 
    """Not a branch: %(path)s"""
199
 
    def __init__(self, path):
200
 
        BzrNewError.__init__(self)
201
 
        self.path = path
202
 
 
203
 
 
204
 
class FileInWrongBranch(BzrNewError):
205
 
    """File %(path)s in not in branch %(branch_base)s."""
206
 
    def __init__(self, branch, path):
207
 
        BzrNewError.__init__(self)
208
 
        self.branch = branch
209
 
        self.branch_base = branch.base
210
 
        self.path = path
 
73
class NotBranchError(BzrError):
 
74
    """Specified path is not in a branch"""
 
75
    def __str__(self):
 
76
        return 'not a branch: %s' % self.args[0]
211
77
 
212
78
 
213
79
class UnsupportedFormatError(BzrError):
216
82
        return 'unsupported branch format: %s' % self.args[0]
217
83
 
218
84
 
219
 
class NotVersionedError(BzrNewError):
220
 
    """%(path)s is not versioned"""
221
 
    def __init__(self, path):
222
 
        BzrNewError.__init__(self)
223
 
        self.path = path
 
85
class NotVersionedError(BzrError):
 
86
    """Specified object is not versioned."""
224
87
 
225
88
 
226
89
class BadFileKindError(BzrError):
227
90
    """Specified file is of a kind that cannot be added.
228
91
 
229
92
    (For example a symlink or device file.)"""
 
93
    pass
230
94
 
231
95
 
232
96
class ForbiddenFileError(BzrError):
233
97
    """Cannot operate on a file because it is a control file."""
 
98
    pass
234
99
 
235
100
 
236
101
class LockError(Exception):
237
 
    """Lock error"""
238
 
    # All exceptions from the lock/unlock functions should be from
239
 
    # this exception class.  They will be translated as necessary. The
240
 
    # original exception is available as e.original_error
 
102
    """All exceptions from the lock/unlock functions should be from
 
103
    this exception class.  They will be translated as necessary. The
 
104
    original exception is available as e.original_error
 
105
    """
 
106
    def __init__(self, e=None):
 
107
        self.original_error = e
 
108
        if e:
 
109
            Exception.__init__(self, e)
 
110
        else:
 
111
            Exception.__init__(self)
241
112
 
242
113
 
243
114
class CommitNotPossible(LockError):
252
123
    """A write attempt was made in a read only transaction."""
253
124
 
254
125
 
255
 
class PointlessCommit(BzrNewError):
256
 
    """No changes to commit"""
 
126
class PointlessCommit(Exception):
 
127
    """Commit failed because nothing was changed."""
257
128
 
258
 
class StrictCommitFailed(Exception):
259
 
    """Commit refused because there are unknowns in the tree."""
260
129
 
261
130
class NoSuchRevision(BzrError):
262
131
    def __init__(self, branch, revision):
276
145
 
277
146
class DivergedBranches(BzrError):
278
147
    def __init__(self, branch1, branch2):
279
 
        BzrError.__init__(self, "These branches have diverged.  Try merge.")
 
148
        BzrError.__init__(self, "These branches have diverged.")
280
149
        self.branch1 = branch1
281
150
        self.branch2 = branch2
282
151
 
308
177
        self.not_ancestor_id = not_ancestor_id
309
178
 
310
179
 
 
180
class NotAncestor(BzrError):
 
181
    def __init__(self, rev_id, not_ancestor_id):
 
182
        self.rev_id = rev_id
 
183
        self.not_ancestor_id = not_ancestor_id
 
184
        msg = "Revision %s is not an ancestor of %s" % (not_ancestor_id, 
 
185
                                                        rev_id)
 
186
        BzrError.__init__(self, msg)
 
187
 
 
188
 
311
189
class InstallFailed(BzrError):
312
190
    def __init__(self, revisions):
313
191
        msg = "Could not install revisions:\n%s" % " ,".join(revisions)
336
214
        BzrError.__init__(self, "Stores for branch %s are not listable" % br)
337
215
 
338
216
 
339
 
class WeaveError(BzrNewError):
340
 
    """Error in processing weave: %(message)s"""
341
 
    def __init__(self, message=None):
342
 
        BzrNewError.__init__(self)
343
 
        self.message = message
344
 
 
345
 
 
346
 
class WeaveRevisionAlreadyPresent(WeaveError):
347
 
    """Revision {%(revision_id)s} already present in %(weave)s"""
348
 
    def __init__(self, revision_id, weave):
349
 
        WeaveError.__init__(self)
350
 
        self.revision_id = revision_id
351
 
        self.weave = weave
352
 
 
353
 
 
354
 
class WeaveRevisionNotPresent(WeaveError):
355
 
    """Revision {%(revision_id)s} not present in %(weave)s"""
356
 
    def __init__(self, revision_id, weave):
357
 
        WeaveError.__init__(self)
358
 
        self.revision_id = revision_id
359
 
        self.weave = weave
360
 
 
361
 
 
362
 
class WeaveFormatError(WeaveError):
363
 
    """Weave invariant violated: %(what)s"""
364
 
    def __init__(self, what):
365
 
        WeaveError.__init__(self)
366
 
        self.what = what
367
 
 
368
 
 
369
 
class WeaveParentMismatch(WeaveError):
370
 
    """Parents are mismatched between two revisions."""
371
 
    
372
 
 
373
 
class NoSuchExportFormat(BzrNewError):
374
 
    """Export format %(format)r not supported"""
375
 
    def __init__(self, format):
376
 
        BzrNewError.__init__(self)
377
 
        self.format = format
378
 
 
 
217
from bzrlib.weave import WeaveError, WeaveParentMismatch
379
218
 
380
219
class TransportError(BzrError):
381
220
    """All errors thrown by Transport implementations should derive
395
234
    """
396
235
    pass
397
236
 
398
 
 
399
 
class ConnectionError(TransportError):
400
 
    """A connection problem prevents file retrieval.
401
 
    This does not indicate whether the file exists or not; it indicates that a
402
 
    precondition for requesting the file was not met.
403
 
    """
404
 
    def __init__(self, msg=None, orig_error=None):
405
 
        TransportError.__init__(self, msg=msg, orig_error=orig_error)
406
 
 
 
237
class NonRelativePath(TransportError):
 
238
    """An absolute path was supplied, that could not be decoded into
 
239
    a relative path.
 
240
    """
 
241
    pass
 
242
 
 
243
class NoSuchFile(TransportError, IOError):
 
244
    """A get() was issued for a file that doesn't exist."""
 
245
 
 
246
    # XXX: Is multiple inheritance for exceptions really needed?
 
247
 
 
248
    def __str__(self):
 
249
        return 'no such file: ' + self.msg
 
250
 
 
251
    def __init__(self, msg=None, orig_error=None):
 
252
        import errno
 
253
        TransportError.__init__(self, msg=msg, orig_error=orig_error)
 
254
        IOError.__init__(self, errno.ENOENT, self.msg)
 
255
 
 
256
class FileExists(TransportError, OSError):
 
257
    """An operation was attempted, which would overwrite an entry,
 
258
    but overwritting is not supported.
 
259
 
 
260
    mkdir() can throw this, but put() just overwites existing files.
 
261
    """
 
262
    # XXX: Is multiple inheritance for exceptions really needed?
 
263
    def __init__(self, msg=None, orig_error=None):
 
264
        import errno
 
265
        TransportError.__init__(self, msg=msg, orig_error=orig_error)
 
266
        OSError.__init__(self, errno.EEXIST, self.msg)
 
267
 
 
268
class PermissionDenied(TransportError):
 
269
    """An operation cannot succeed because of a lack of permissions."""
 
270
    pass
407
271
 
408
272
class ConnectionReset(TransportError):
409
273
    """The connection has been closed."""
413
277
    def __init__(self):
414
278
        BzrError.__init__(self, "Working tree has conflicts.")
415
279
 
416
 
class ParseConfigError(BzrError):
417
 
    def __init__(self, errors, filename):
418
 
        if filename is None:
419
 
            filename = ""
420
 
        message = "Error(s) parsing config file %s:\n%s" % \
421
 
            (filename, ('\n'.join(e.message for e in errors)))
422
 
        BzrError.__init__(self, message)
423
 
 
424
280
class SigningFailed(BzrError):
425
281
    def __init__(self, command_line):
426
282
        BzrError.__init__(self, "Failed to gpg sign data with command '%s'"
427
283
                               % command_line)
428
 
 
429
 
class WorkingTreeNotRevision(BzrError):
430
 
    def __init__(self, tree):
431
 
        BzrError.__init__(self, "The working tree for %s has changed since"
432
 
                          " last commit, but weave merge requires that it be"
433
 
                          " unchanged." % tree.basedir)
434
 
 
435
 
class CantReprocessAndShowBase(BzrNewError):
436
 
    """Can't reprocess and show base.
437
 
Reprocessing obscures relationship of conflicting lines to base."""
438
 
 
439
 
class GraphCycleError(BzrNewError):
440
 
    """Cycle in graph %(graph)r"""
441
 
    def __init__(self, graph):
442
 
        BzrNewError.__init__(self)
443
 
        self.graph = graph
444
 
 
445
 
class NotConflicted(BzrNewError):
446
 
    """File %(filename)s is not conflicted."""
447
 
    def __init__(self, filename):
448
 
        BzrNewError.__init__(self)
449
 
        self.filename = filename
450
 
 
451
 
class MustUseDecorated(Exception):
452
 
    """A decorating function has requested its original command be used.
453
 
    
454
 
    This should never escape bzr, so does not need to be printable.
455
 
    """
456
 
 
457
 
class MissingText(BzrNewError):
458
 
    """Branch %(base)s is missing revision %(text_revision)s of %(file_id)s"""
459
 
    def __init__(self, branch, text_revision, file_id):
460
 
        self.branch = branch
461
 
        self.base = branch.base
462
 
        self.text_revision = text_revision
463
 
        self.file_id = file_id