File: _errors.py

package info (click to toggle)
notmuch 0.39-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 7,104 kB
  • sloc: sh: 21,888; ansic: 14,897; lisp: 9,061; cpp: 7,990; python: 6,221; perl: 391; makefile: 231; javascript: 34; ruby: 13
file content (124 lines) | stat: -rw-r--r-- 4,652 bytes parent folder | download | duplicates (3)
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
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_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 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'