Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
"""
-
+import sys
from ctypes import CDLL, c_char_p, c_int, Structure, POINTER
-from ctypes.util import find_library
#-----------------------------------------------------------------------------
#package-global instance of the notmuch library
raise ImportError("Could not find shared 'notmuch' library.")
+if sys.version_info[0] == 2:
+ class Python3StringMixIn(object):
+ def __str__(self):
+ return unicode(self).encode('utf-8')
+
+
+ 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" % type(value))
+ if isinstance(value, unicode):
+ return value.encode('UTF-8')
+ return value
+else:
+ class Python3StringMixIn(object):
+ def __str__(self):
+ return self.__unicode__()
+
+
+ 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, str):
+ raise TypeError("Expected str, got %s" % type(value))
+ return value.encode('UTF-8')
+
+
class Enum(object):
"""Provides ENUMS as "code=Enum(['a','b','c'])" where code.a=0 etc..."""
def __init__(self, names):
@classmethod
def status2str(self, status):
- """Get a string representation of a notmuch_status_t value."""
+ """Get a (unicode) 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))
+ return unicode(Status._status2str(status))
STATUS = Status(['SUCCESS',
'OUT_OF_MEMORY',
argument to receive a human readable string"""
STATUS.__name__ = 'STATUS'
-class NotmuchError(Exception):
+
+class NotmuchError(Exception, Python3StringMixIn):
"""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
@classmethod
def get_exc_subclass(cls, status):
- """Returns a fine grained Exception() type,detailing the error status"""
+ """Returns a fine grained Exception() type,
+ detailing the error status"""
subclasses = {
STATUS.OUT_OF_MEMORY: OutOfMemoryError,
STATUS.READ_ONLY_DATABASE: ReadOnlyDatabaseError,
STATUS.TAG_TOO_LONG: TagTooLongError,
STATUS.UNBALANCED_FREEZE_THAW: UnbalancedFreezeThawError,
STATUS.UNBALANCED_ATOMIC: UnbalancedAtomicError,
- STATUS.NOT_INITIALIZED: NotInitializedError
+ STATUS.NOT_INITIALIZED: NotInitializedError,
}
assert 0 < status <= len(subclasses)
return subclasses[status]
# no 'status' or cls is subclass already, return 'cls' instance
if not status or cls != NotmuchError:
return super(NotmuchError, cls).__new__(cls)
- subclass = cls.get_exc_subclass(status) # which class to use?
+ subclass = cls.get_exc_subclass(status) # which class to use?
return subclass.__new__(subclass, *args, **kwargs)
def __init__(self, status=None, message=None):
self.status = status
self.message = message
- def __str__(self):
+ def __unicode__(self):
if self.message is not None:
return self.message
elif self.status is not None:
else:
return 'Unknown error'
+
# List of Subclassed exceptions that correspond to STATUS values and are
# subclasses of NotmuchError.
class OutOfMemoryError(NotmuchError):
status = STATUS.OUT_OF_MEMORY
+
+
class ReadOnlyDatabaseError(NotmuchError):
status = STATUS.READ_ONLY_DATABASE
+
+
class XapianError(NotmuchError):
status = STATUS.XAPIAN_EXCEPTION
+
+
class FileError(NotmuchError):
status = STATUS.FILE_ERROR
+
+
class FileNotEmailError(NotmuchError):
status = STATUS.FILE_NOT_EMAIL
+
+
class DuplicateMessageIdError(NotmuchError):
status = STATUS.DUPLICATE_MESSAGE_ID
+
+
class NullPointerError(NotmuchError):
status = STATUS.NULL_POINTER
+
+
class TagTooLongError(NotmuchError):
status = STATUS.TAG_TOO_LONG
+
+
class UnbalancedFreezeThawError(NotmuchError):
status = STATUS.UNBALANCED_FREEZE_THAW
+
+
class UnbalancedAtomicError(NotmuchError):
status = STATUS.UNBALANCED_ATOMIC
+
+
class NotInitializedError(NotmuchError):
"""Derived from NotmuchError, this occurs if the underlying data
structure (e.g. database is not initialized (yet) or an iterator has
status = STATUS.NOT_INITIALIZED
-
-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
-
-
class NotmuchDatabaseS(Structure):
pass
NotmuchDatabaseP = POINTER(NotmuchDatabaseS)
+
class NotmuchQueryS(Structure):
pass
NotmuchQueryP = POINTER(NotmuchQueryS)
+
class NotmuchThreadsS(Structure):
pass
NotmuchThreadsP = POINTER(NotmuchThreadsS)
+
class NotmuchThreadS(Structure):
pass
NotmuchThreadP = POINTER(NotmuchThreadS)
+
class NotmuchMessagesS(Structure):
pass
NotmuchMessagesP = POINTER(NotmuchMessagesS)
+
class NotmuchMessageS(Structure):
pass
NotmuchMessageP = POINTER(NotmuchMessageS)
+
class NotmuchTagsS(Structure):
pass
NotmuchTagsP = POINTER(NotmuchTagsS)
+
class NotmuchDirectoryS(Structure):
pass
NotmuchDirectoryP = POINTER(NotmuchDirectoryS)
+
class NotmuchFilenamesS(Structure):
pass
NotmuchFilenamesP = POINTER(NotmuchFilenamesS)