aboutsummaryrefslogtreecommitdiffhomepage
path: root/bindings/python/notmuch/globals.py
blob: 5fca3d9bd7fc1bc4c02e5b8ef2bc2d26dee04822 (plain)
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
"""
This file is part of notmuch.

Notmuch is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.

Notmuch is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with notmuch.  If not, see <http://www.gnu.org/licenses/>.

Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
"""

from ctypes import CDLL, c_char_p, c_int
from ctypes.util import find_library

#-----------------------------------------------------------------------------
#package-global instance of the notmuch library
try:
    nmlib = CDLL("libnotmuch.so.1")
except:
    raise ImportError("Could not find shared 'notmuch' library.")


class Enum(object):
    """Provides ENUMS as "code=Enum(['a','b','c'])" where code.a=0 etc..."""
    def __init__(self, names):
        for number, name in enumerate(names):
            setattr(self, name, number)


class Status(Enum):
    """Enum with a string representation of a notmuch_status_t value."""
    _status2str = nmlib.notmuch_status_to_string
    _status2str.restype = c_char_p
    _status2str.argtypes = [c_int]

    def __init__(self, statuslist):
        """It is initialized with a list of strings that are available as
        Status().string1 - Status().stringn attributes.
        """
        super(Status, self).__init__(statuslist)

    @classmethod
    def status2str(self, status):
        """Get a string representation of a notmuch_status_t value."""
        # define strings for custom error messages
        if status == STATUS.NOT_INITIALIZED:
            return "Operation on uninitialized object impossible."
        return str(Status._status2str(status))

STATUS = Status(['SUCCESS',
  'OUT_OF_MEMORY',
  'READ_ONLY_DATABASE',
  'XAPIAN_EXCEPTION',
  'FILE_ERROR',
  'FILE_NOT_EMAIL',
  'DUPLICATE_MESSAGE_ID',
  'NULL_POINTER',
  'TAG_TOO_LONG',
  'UNBALANCED_FREEZE_THAW',
  'UNBALANCED_ATOMIC',
  'NOT_INITIALIZED'])
"""STATUS is a class, whose attributes provide constants that serve as return
indicators for notmuch functions. Currently the following ones are defined. For
possible return values and specific meaning for each method, see the method
description.

  * SUCCESS
  * OUT_OF_MEMORY
  * READ_ONLY_DATABASE
  * XAPIAN_EXCEPTION
  * FILE_ERROR
  * FILE_NOT_EMAIL
  * DUPLICATE_MESSAGE_ID
  * NULL_POINTER
  * TAG_TOO_LONG
  * UNBALANCED_FREEZE_THAW
  * UNBALANCED_ATOMIC
  * NOT_INITIALIZED

Invoke the class method `notmuch.STATUS.status2str` with a status value as
argument to receive a human readable string"""
STATUS.__name__ = 'STATUS'

class NotmuchError(Exception):
    """Is initiated with a (notmuch.STATUS[, message=None]). It will not
    return an instance of the class NotmuchError, but a derived instance
    of a more specific Error Message, e.g. OutOfMemoryError. Each status
    but SUCCESS has a corresponding subclassed Exception."""

    @classmethod
    def get_subclass_exc(cls, status, message=None):
        """Returns a fine grained Exception() type,detailing the error status"""
        subclasses = {
            STATUS.OUT_OF_MEMORY: OutOfMemoryError,
            STATUS.READ_ONLY_DATABASE: ReadOnlyDatabaseError,
            STATUS.XAPIAN_EXCEPTION: XapianError,
            STATUS.FILE_ERROR: FileError,
            STATUS.FILE_NOT_EMAIL: FileNotEmailError,
            STATUS.DUPLICATE_MESSAGE_ID: DuplicateMessageIdError,
            STATUS.NULL_POINTER: NullPointerError,
            STATUS.TAG_TOO_LONG: TagTooLongError,
            STATUS.UNBALANCED_FREEZE_THAW: UnbalancedFreezeThawError,
            STATUS.UNBALANCED_ATOMIC: UnbalancedAtomicError,
            STATUS.NOT_INITIALIZED: NotInitializedError
        }
        assert 0 < status <= len(subclasses)
        return subclasses[status](status, message)

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

    def __str__(self):
        if self.message is not None:
            return self.message
        elif self.status is not None:
            return STATUS.status2str(self.status)
        else:
            return 'Unknown error'

# List of Subclassed exceptions that correspond to STATUS values and are
# subclasses of NotmuchError:
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 NotInitializedError(NotmuchError):
    pass


def _str(value):
    """Ensure a nicely utf-8 encoded string to pass to libnotmuch

    C++ code expects strings to be well formatted and
    unicode strings to have no null bytes."""
    if not isinstance(value, basestring):
        raise TypeError("Expected str or unicode, got %s" % str(type(value)))
    if isinstance(value, unicode):
        return value.encode('UTF-8')
    return value