~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/errors.py

  • Committer: John Arbash Meinel
  • Date: 2005-11-08 18:36:26 UTC
  • mto: This revision was merged to the branch mainline in revision 1727.
  • Revision ID: john@arbash-meinel.com-20051108183626-71f8414338043265
Updating unified_diff to take a factory, using the new diff algorithm in the code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: UTF-8 -*-
 
1
# (C) 2005 Canonical
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
 
 
18
 
__copyright__ = "Copyright (C) 2005 Canonical Ltd."
19
 
__author__ = "Martin Pool <mbp@canonical.com>"
20
 
 
21
 
 
22
 
######################################################################
23
 
# exceptions 
 
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
 
 
51
# based on Scott James Remnant's hct error classes
 
52
 
 
53
# TODO: is there any value in providing the .args field used by standard
 
54
# python exceptions?   A list of values with no names seems less useful 
 
55
# to me.
 
56
 
 
57
# TODO: Perhaps convert the exception to a string at the moment it's 
 
58
# constructed to make sure it will succeed.  But that says nothing about
 
59
# exceptions that are never raised.
 
60
 
 
61
# TODO: Convert all the other error classes here to BzrNewError, and eliminate
 
62
# the old one.
 
63
 
 
64
 
24
65
class BzrError(StandardError):
25
 
    pass
26
 
 
27
 
 
28
 
class BzrCheckError(BzrError):
29
 
    pass
30
 
 
31
 
 
32
 
class InvalidRevisionNumber(BzrError):
 
66
    def __str__(self):
 
67
        # XXX: Should we show the exception class in 
 
68
        # exceptions that don't provide their own message?  
 
69
        # maybe it should be done at a higher level
 
70
        ## n = self.__class__.__name__ + ': '
 
71
        n = ''
 
72
        if len(self.args) == 1:
 
73
            return str(self.args[0])
 
74
        elif len(self.args) == 2:
 
75
            # further explanation or suggestions
 
76
            try:
 
77
                return n + '\n  '.join([self.args[0]] + self.args[1])
 
78
            except TypeError:
 
79
                return n + "%r" % self
 
80
        else:
 
81
            return n + `self.args`
 
82
 
 
83
 
 
84
class BzrNewError(BzrError):
 
85
    """bzr error"""
 
86
    # base classes should override the docstring with their human-
 
87
    # readable explanation
 
88
 
 
89
    def __init__(self, **kwds):
 
90
        for key, value in kwds.items():
 
91
            setattr(self, key, value)
 
92
 
 
93
    def __str__(self):
 
94
        try:
 
95
            return self.__doc__ % self.__dict__
 
96
        except (NameError, ValueError, KeyError), e:
 
97
            return 'Unprintable exception %s: %s' \
 
98
                % (self.__class__.__name__, str(e))
 
99
 
 
100
 
 
101
class BzrCheckError(BzrNewError):
 
102
    """Internal check failed: %(message)s"""
 
103
    def __init__(self, message):
 
104
        BzrNewError.__init__(self)
 
105
        self.message = message
 
106
 
 
107
 
 
108
class InvalidEntryName(BzrNewError):
 
109
    """Invalid entry name: %(name)s"""
 
110
    def __init__(self, name):
 
111
        BzrNewError.__init__(self)
 
112
        self.name = name
 
113
 
 
114
 
 
115
class InvalidRevisionNumber(BzrNewError):
 
116
    """Invalid revision number %(revno)d"""
33
117
    def __init__(self, revno):
34
 
        self.args = [revno]
 
118
        BzrNewError.__init__(self)
 
119
        self.revno = revno
 
120
 
 
121
 
 
122
class InvalidRevisionId(BzrNewError):
 
123
    """Invalid revision-id {%(revision_id)s} in %(branch)s"""
 
124
    def __init__(self, revision_id, branch):
 
125
        BzrNewError.__init__(self)
 
126
        self.revision_id = revision_id
 
127
        self.branch = branch
 
128
 
 
129
 
 
130
class NoWorkingTree(BzrNewError):
 
131
    """No WorkingTree exists for %s(base)."""
 
132
    
 
133
    def __init__(self, base):
 
134
        BzrNewError.__init__(self)
 
135
        self.base = base
35
136
        
36
 
    def __str__(self):
37
 
        return 'invalid revision number: %r' % self.args[0]
38
 
 
39
 
 
40
 
class InvalidRevisionId(BzrError):
41
 
    pass
42
 
 
43
137
 
44
138
class BzrCommandError(BzrError):
45
139
    # Error from malformed user command
46
 
    pass
47
 
 
48
 
 
49
 
class NotBranchError(BzrError):
50
 
    """Specified path is not in a branch"""
51
 
    pass
52
 
 
53
 
 
54
 
class NotVersionedError(BzrError):
55
 
    """Specified object is not versioned."""
 
140
    # This is being misused as a generic exception
 
141
    # pleae subclass. RBC 20051030
 
142
    def __str__(self):
 
143
        return self.args[0]
 
144
 
 
145
 
 
146
class BzrOptionError(BzrCommandError):
 
147
    """Some missing or otherwise incorrect option was supplied."""
 
148
 
 
149
    
 
150
class StrictCommitFailed(Exception):
 
151
    """Commit refused because there are unknowns in the tree."""
 
152
 
 
153
class NotBranchError(BzrNewError):
 
154
    """Not a branch: %(path)s"""
 
155
    def __init__(self, path):
 
156
        BzrNewError.__init__(self)
 
157
        self.path = path
 
158
 
 
159
 
 
160
class UnsupportedFormatError(BzrError):
 
161
    """Specified path is a bzr branch that we cannot read."""
 
162
    def __str__(self):
 
163
        return 'unsupported branch format: %s' % self.args[0]
 
164
 
 
165
 
 
166
class NotVersionedError(BzrNewError):
 
167
    """%(path)s is not versioned"""
 
168
    def __init__(self, path):
 
169
        BzrNewError.__init__(self)
 
170
        self.path = path
56
171
 
57
172
 
58
173
class BadFileKindError(BzrError):
59
174
    """Specified file is of a kind that cannot be added.
60
175
 
61
176
    (For example a symlink or device file.)"""
62
 
    pass
63
177
 
64
178
 
65
179
class ForbiddenFileError(BzrError):
66
180
    """Cannot operate on a file because it is a control file."""
67
 
    pass
68
181
 
69
182
 
70
183
class LockError(Exception):
71
 
    """All exceptions from the lock/unlock functions should be from
72
 
    this exception class.  They will be translated as necessary. The
73
 
    original exception is available as e.original_error
74
 
    """
75
 
    def __init__(self, e=None):
76
 
        self.original_error = e
77
 
        if e:
78
 
            Exception.__init__(self, e)
79
 
        else:
80
 
            Exception.__init__(self)
81
 
 
82
 
 
83
 
class PointlessCommit(Exception):
84
 
    """Commit failed because nothing was changed."""
85
 
 
 
184
    """Lock error"""
 
185
    # All exceptions from the lock/unlock functions should be from
 
186
    # this exception class.  They will be translated as necessary. The
 
187
    # original exception is available as e.original_error
 
188
 
 
189
 
 
190
class CommitNotPossible(LockError):
 
191
    """A commit was attempted but we do not have a write lock open."""
 
192
 
 
193
 
 
194
class AlreadyCommitted(LockError):
 
195
    """A rollback was requested, but is not able to be accomplished."""
 
196
 
 
197
 
 
198
class ReadOnlyError(LockError):
 
199
    """A write attempt was made in a read only transaction."""
 
200
 
 
201
 
 
202
class PointlessCommit(BzrNewError):
 
203
    """No changes to commit"""
 
204
 
 
205
class StrictCommitFailed(Exception):
 
206
    """Commit refused because there are unknowns in the tree."""
86
207
 
87
208
class NoSuchRevision(BzrError):
88
209
    def __init__(self, branch, revision):
92
213
        BzrError.__init__(self, msg)
93
214
 
94
215
 
 
216
class HistoryMissing(BzrError):
 
217
    def __init__(self, branch, object_type, object_id):
 
218
        self.branch = branch
 
219
        BzrError.__init__(self,
 
220
                          '%s is missing %s {%s}'
 
221
                          % (branch, object_type, object_id))
 
222
 
 
223
 
95
224
class DivergedBranches(BzrError):
96
225
    def __init__(self, branch1, branch2):
97
226
        BzrError.__init__(self, "These branches have diverged.")
98
227
        self.branch1 = branch1
99
228
        self.branch2 = branch2
100
229
 
 
230
 
101
231
class UnrelatedBranches(BzrCommandError):
102
232
    def __init__(self):
103
233
        msg = "Branches have no common ancestor, and no base revision"\
125
255
        self.not_ancestor_id = not_ancestor_id
126
256
 
127
257
 
 
258
class NotAncestor(BzrError):
 
259
    def __init__(self, rev_id, not_ancestor_id):
 
260
        self.rev_id = rev_id
 
261
        self.not_ancestor_id = not_ancestor_id
 
262
        msg = "Revision %s is not an ancestor of %s" % (not_ancestor_id, 
 
263
                                                        rev_id)
 
264
        BzrError.__init__(self, msg)
 
265
 
 
266
 
128
267
class InstallFailed(BzrError):
129
268
    def __init__(self, revisions):
130
269
        msg = "Could not install revisions:\n%s" % " ,".join(revisions)
143
282
    def __init__(self, branch):
144
283
        msg = "Branch %s has no commits." % branch
145
284
        BzrError.__init__(self, msg)
 
285
 
 
286
class UnlistableStore(BzrError):
 
287
    def __init__(self, store):
 
288
        BzrError.__init__(self, "Store %s is not listable" % store)
 
289
 
 
290
class UnlistableBranch(BzrError):
 
291
    def __init__(self, br):
 
292
        BzrError.__init__(self, "Stores for branch %s are not listable" % br)
 
293
 
 
294
 
 
295
class WeaveError(BzrNewError):
 
296
    """Error in processing weave: %(message)s"""
 
297
    def __init__(self, message=None):
 
298
        BzrNewError.__init__(self)
 
299
        self.message = message
 
300
 
 
301
 
 
302
class WeaveRevisionAlreadyPresent(WeaveError):
 
303
    """Revision {%(revision_id)s} already present in %(weave)s"""
 
304
    def __init__(self, revision_id, weave):
 
305
        WeaveError.__init__(self)
 
306
        self.revision_id = revision_id
 
307
        self.weave = weave
 
308
 
 
309
 
 
310
class WeaveRevisionNotPresent(WeaveError):
 
311
    """Revision {%(revision_id)s} not present in %(weave)s"""
 
312
    def __init__(self, revision_id, weave):
 
313
        WeaveError.__init__(self)
 
314
        self.revision_id = revision_id
 
315
        self.weave = weave
 
316
 
 
317
 
 
318
class WeaveFormatError(WeaveError):
 
319
    """Weave invariant violated: %(what)s"""
 
320
    def __init__(self, what):
 
321
        WeaveError.__init__(self)
 
322
        self.what = what
 
323
 
 
324
 
 
325
class WeaveParentMismatch(WeaveError):
 
326
    """Parents are mismatched between two revisions."""
 
327
    
 
328
 
 
329
class TransportError(BzrError):
 
330
    """All errors thrown by Transport implementations should derive
 
331
    from this class.
 
332
    """
 
333
    def __init__(self, msg=None, orig_error=None):
 
334
        if msg is None and orig_error is not None:
 
335
            msg = str(orig_error)
 
336
        BzrError.__init__(self, msg)
 
337
        self.msg = msg
 
338
        self.orig_error = orig_error
 
339
 
 
340
# A set of semi-meaningful errors which can be thrown
 
341
class TransportNotPossible(TransportError):
 
342
    """This is for transports where a specific function is explicitly not
 
343
    possible. Such as pushing files to an HTTP server.
 
344
    """
 
345
    pass
 
346
 
 
347
class NonRelativePath(TransportError):
 
348
    """An absolute path was supplied, that could not be decoded into
 
349
    a relative path.
 
350
    """
 
351
    pass
 
352
 
 
353
class NoSuchFile(TransportError, IOError):
 
354
    """A get() was issued for a file that doesn't exist."""
 
355
 
 
356
    # XXX: Is multiple inheritance for exceptions really needed?
 
357
 
 
358
    def __str__(self):
 
359
        return 'no such file: ' + self.msg
 
360
 
 
361
    def __init__(self, msg=None, orig_error=None):
 
362
        import errno
 
363
        TransportError.__init__(self, msg=msg, orig_error=orig_error)
 
364
        IOError.__init__(self, errno.ENOENT, self.msg)
 
365
 
 
366
class FileExists(TransportError, OSError):
 
367
    """An operation was attempted, which would overwrite an entry,
 
368
    but overwritting is not supported.
 
369
 
 
370
    mkdir() can throw this, but put() just overwites existing files.
 
371
    """
 
372
    # XXX: Is multiple inheritance for exceptions really needed?
 
373
    def __init__(self, msg=None, orig_error=None):
 
374
        import errno
 
375
        TransportError.__init__(self, msg=msg, orig_error=orig_error)
 
376
        OSError.__init__(self, errno.EEXIST, self.msg)
 
377
 
 
378
class PermissionDenied(TransportError):
 
379
    """An operation cannot succeed because of a lack of permissions."""
 
380
    pass
 
381
 
 
382
class ConnectionReset(TransportError):
 
383
    """The connection has been closed."""
 
384
    pass
 
385
 
 
386
class ConflictsInTree(BzrError):
 
387
    def __init__(self):
 
388
        BzrError.__init__(self, "Working tree has conflicts.")
 
389
 
 
390
class ParseConfigError(BzrError):
 
391
    def __init__(self, errors, filename):
 
392
        if filename is None:
 
393
            filename = ""
 
394
        message = "Error(s) parsing config file %s:\n%s" % \
 
395
            (filename, ('\n'.join(e.message for e in errors)))
 
396
        BzrError.__init__(self, message)
 
397
 
 
398
class SigningFailed(BzrError):
 
399
    def __init__(self, command_line):
 
400
        BzrError.__init__(self, "Failed to gpg sign data with command '%s'"
 
401
                               % command_line)
 
402
 
 
403
class WorkingTreeNotRevision(BzrError):
 
404
    def __init__(self, tree):
 
405
        BzrError.__init__(self, "The working tree for %s has changed since"
 
406
                          " last commit, but weave merge requires that it be"
 
407
                          " unchanged." % tree.basedir)
 
408
 
 
409
class CantReprocessAndShowBase(BzrNewError):
 
410
    """Can't reprocess and show base.
 
411
Reprocessing obscures relationship of conflicting lines to base."""
 
412
 
 
413
class GraphCycleError(BzrNewError):
 
414
    """Cycle in graph %(graph)r"""
 
415
    def __init__(self, graph):
 
416
        BzrNewError.__init__(self)
 
417
        self.graph = graph
 
418
 
 
419
class MustUseDecorated(Exception):
 
420
    """A decorating function has requested its original command be used.
 
421
    
 
422
    This should never escape bzr, so does not need to be printable.
 
423
    """
 
424