]> git.notmuchmail.org Git - notmuch/blob - bindings/python-cffi/notmuch2/_errors.py
emacs: Add new option notmuch-search-hide-excluded
[notmuch] / bindings / python-cffi / notmuch2 / _errors.py
1 from notmuch2 import _capi as capi
2
3
4 class NotmuchError(Exception):
5     """Base exception for errors originating from the notmuch library.
6
7     Usually this will have two attributes:
8
9     :status: This is a numeric status code corresponding to the error
10        code in the notmuch library.  This is normally fairly
11        meaningless, it can also often be ``None``.  This exists mostly
12        to easily create new errors from notmuch status codes and
13        should not normally be used by users.
14
15     :message: A user-facing message for the error.  This can
16        occasionally also be ``None``.  Usually you'll want to call
17        ``str()`` on the error object instead to get a sensible
18        message.
19     """
20
21     @classmethod
22     def exc_type(cls, status):
23         """Return correct exception type for notmuch status."""
24         types = {
25             capi.lib.NOTMUCH_STATUS_OUT_OF_MEMORY:
26                 OutOfMemoryError,
27             capi.lib.NOTMUCH_STATUS_READ_ONLY_DATABASE:
28                 ReadOnlyDatabaseError,
29             capi.lib.NOTMUCH_STATUS_XAPIAN_EXCEPTION:
30                 XapianError,
31             capi.lib.NOTMUCH_STATUS_FILE_ERROR:
32                 FileError,
33             capi.lib.NOTMUCH_STATUS_FILE_NOT_EMAIL:
34                 FileNotEmailError,
35             capi.lib.NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
36                 DuplicateMessageIdError,
37             capi.lib.NOTMUCH_STATUS_NULL_POINTER:
38                 NullPointerError,
39             capi.lib.NOTMUCH_STATUS_TAG_TOO_LONG:
40                 TagTooLongError,
41             capi.lib.NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
42                 UnbalancedFreezeThawError,
43             capi.lib.NOTMUCH_STATUS_UNBALANCED_ATOMIC:
44                 UnbalancedAtomicError,
45             capi.lib.NOTMUCH_STATUS_UNSUPPORTED_OPERATION:
46                 UnsupportedOperationError,
47             capi.lib.NOTMUCH_STATUS_UPGRADE_REQUIRED:
48                 UpgradeRequiredError,
49             capi.lib.NOTMUCH_STATUS_PATH_ERROR:
50                 PathError,
51             capi.lib.NOTMUCH_STATUS_ILLEGAL_ARGUMENT:
52                 IllegalArgumentError,
53             capi.lib.NOTMUCH_STATUS_NO_CONFIG:
54                 NoConfigError,
55             capi.lib.NOTMUCH_STATUS_NO_DATABASE:
56                 NoDatabaseError,
57             capi.lib.NOTMUCH_STATUS_DATABASE_EXISTS:
58                 DatabaseExistsError,
59             capi.lib.NOTMUCH_STATUS_BAD_QUERY_SYNTAX:
60                 QuerySyntaxError,
61         }
62         return types[status]
63
64     def __new__(cls, *args, **kwargs):
65         """Return the correct subclass based on status."""
66         # This is simplistic, but the actual __init__ will fail if the
67         # signature is wrong anyway.
68         if args:
69             status = args[0]
70         else:
71             status = kwargs.get('status', None)
72         if status and cls == NotmuchError:
73             exc = cls.exc_type(status)
74             return exc.__new__(exc, *args, **kwargs)
75         else:
76             return super().__new__(cls)
77
78     def __init__(self, status=None, message=None):
79         self.status = status
80         self.message = message
81
82     def __str__(self):
83         if self.message:
84             return self.message
85         elif self.status:
86             char_str = capi.lib.notmuch_status_to_string(self.status)
87             return capi.ffi.string(char_str).decode(errors='replace')
88         else:
89             return 'Unknown error'
90
91
92 class OutOfMemoryError(NotmuchError): pass
93 class ReadOnlyDatabaseError(NotmuchError): pass
94 class XapianError(NotmuchError): pass
95 class FileError(NotmuchError): pass
96 class FileNotEmailError(NotmuchError): pass
97 class DuplicateMessageIdError(NotmuchError): pass
98 class NullPointerError(NotmuchError): pass
99 class TagTooLongError(NotmuchError): pass
100 class UnbalancedFreezeThawError(NotmuchError): pass
101 class UnbalancedAtomicError(NotmuchError): pass
102 class UnsupportedOperationError(NotmuchError): pass
103 class UpgradeRequiredError(NotmuchError): pass
104 class PathError(NotmuchError): pass
105 class IllegalArgumentError(NotmuchError): pass
106 class NoConfigError(NotmuchError): pass
107 class NoDatabaseError(NotmuchError): pass
108 class DatabaseExistsError(NotmuchError): pass
109 class QuerySyntaxError(NotmuchError): pass
110
111 class ObjectDestroyedError(NotmuchError):
112     """The object has already been destroyed and it's memory freed.
113
114     This occurs when :meth:`destroy` has been called on the object but
115     you still happen to have access to the object.  This should not
116     normally occur since you should never call :meth:`destroy` by
117     hand.
118     """
119
120     def __str__(self):
121         if self.message:
122             return self.message
123         else:
124             return 'Memory already freed'