File: _errors.py

package info (click to toggle)
notmuch 0.40-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,120 kB
  • sloc: sh: 22,063; ansic: 14,938; lisp: 9,090; cpp: 8,030; python: 6,342; perl: 391; makefile: 231; javascript: 34; ruby: 9
file content (127 lines) | stat: -rw-r--r-- 4,805 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
from notmuch2 import _capi as capi


class NotmuchError(Exception):
    """Base exception for errors originating from the notmuch library.

    Usually this will have two attributes:

    :status: This is a numeric status code corresponding to the error
       code in the notmuch library.  This is normally fairly
       meaningless, it can also often be ``None``.  This exists mostly
       to easily create new errors from notmuch status codes and
       should not normally be used by users.

    :message: A user-facing message for the error.  This can
       occasionally also be ``None``.  Usually you'll want to call
       ``str()`` on the error object instead to get a sensible
       message.
    """

    @classmethod
    def exc_type(cls, status):
        """Return correct exception type for notmuch status."""
        types = {
            capi.lib.NOTMUCH_STATUS_OUT_OF_MEMORY:
                OutOfMemoryError,
            capi.lib.NOTMUCH_STATUS_READ_ONLY_DATABASE:
                ReadOnlyDatabaseError,
            capi.lib.NOTMUCH_STATUS_XAPIAN_EXCEPTION:
                XapianError,
            capi.lib.NOTMUCH_STATUS_OPERATION_INVALIDATED:
                OperationInvalidatedError,
            capi.lib.NOTMUCH_STATUS_FILE_ERROR:
                FileError,
            capi.lib.NOTMUCH_STATUS_FILE_NOT_EMAIL:
                FileNotEmailError,
            capi.lib.NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
                DuplicateMessageIdError,
            capi.lib.NOTMUCH_STATUS_NULL_POINTER:
                NullPointerError,
            capi.lib.NOTMUCH_STATUS_TAG_TOO_LONG:
                TagTooLongError,
            capi.lib.NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
                UnbalancedFreezeThawError,
            capi.lib.NOTMUCH_STATUS_UNBALANCED_ATOMIC:
                UnbalancedAtomicError,
            capi.lib.NOTMUCH_STATUS_UNSUPPORTED_OPERATION:
                UnsupportedOperationError,
            capi.lib.NOTMUCH_STATUS_UPGRADE_REQUIRED:
                UpgradeRequiredError,
            capi.lib.NOTMUCH_STATUS_PATH_ERROR:
                PathError,
            capi.lib.NOTMUCH_STATUS_ILLEGAL_ARGUMENT:
                IllegalArgumentError,
            capi.lib.NOTMUCH_STATUS_NO_CONFIG:
                NoConfigError,
            capi.lib.NOTMUCH_STATUS_NO_DATABASE:
                NoDatabaseError,
            capi.lib.NOTMUCH_STATUS_DATABASE_EXISTS:
                DatabaseExistsError,
            capi.lib.NOTMUCH_STATUS_BAD_QUERY_SYNTAX:
                QuerySyntaxError,
        }
        return types[status]

    def __new__(cls, *args, **kwargs):
        """Return the correct subclass based on status."""
        # This is simplistic, but the actual __init__ will fail if the
        # signature is wrong anyway.
        if args:
            status = args[0]
        else:
            status = kwargs.get('status', None)
        if status and cls == NotmuchError:
            exc = cls.exc_type(status)
            return exc.__new__(exc, *args, **kwargs)
        else:
            return super().__new__(cls)

    def __init__(self, status=None, message=None):
        self.status = status
        self.message = message

    def __str__(self):
        if self.message:
            return self.message
        elif self.status:
            char_str = capi.lib.notmuch_status_to_string(self.status)
            return capi.ffi.string(char_str).decode(errors='replace')
        else:
            return 'Unknown error'


class OutOfMemoryError(NotmuchError): pass
class ReadOnlyDatabaseError(NotmuchError): pass
class XapianError(NotmuchError): pass
class OperationInvalidatedError(XapianError): pass
class FileError(NotmuchError): pass
class FileNotEmailError(NotmuchError): pass
class DuplicateMessageIdError(NotmuchError): pass
class NullPointerError(NotmuchError): pass
class TagTooLongError(NotmuchError): pass
class UnbalancedFreezeThawError(NotmuchError): pass
class UnbalancedAtomicError(NotmuchError): pass
class UnsupportedOperationError(NotmuchError): pass
class UpgradeRequiredError(NotmuchError): pass
class PathError(NotmuchError): pass
class IllegalArgumentError(NotmuchError): pass
class NoConfigError(NotmuchError): pass
class NoDatabaseError(NotmuchError): pass
class DatabaseExistsError(NotmuchError): pass
class QuerySyntaxError(NotmuchError): pass

class ObjectDestroyedError(NotmuchError):
    """The object has already been destroyed and it's memory freed.

    This occurs when :meth:`destroy` has been called on the object but
    you still happen to have access to the object.  This should not
    normally occur since you should never call :meth:`destroy` by
    hand.
    """

    def __str__(self):
        if self.message:
            return self.message
        else:
            return 'Memory already freed'