1from notmuch2 import _capi as capi 2 3 4class 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 92class OutOfMemoryError(NotmuchError): pass 93class ReadOnlyDatabaseError(NotmuchError): pass 94class XapianError(NotmuchError): pass 95class FileError(NotmuchError): pass 96class FileNotEmailError(NotmuchError): pass 97class DuplicateMessageIdError(NotmuchError): pass 98class NullPointerError(NotmuchError): pass 99class TagTooLongError(NotmuchError): pass 100class UnbalancedFreezeThawError(NotmuchError): pass 101class UnbalancedAtomicError(NotmuchError): pass 102class UnsupportedOperationError(NotmuchError): pass 103class UpgradeRequiredError(NotmuchError): pass 104class PathError(NotmuchError): pass 105class IllegalArgumentError(NotmuchError): pass 106class NoConfigError(NotmuchError): pass 107class NoDatabaseError(NotmuchError): pass 108class DatabaseExistsError(NotmuchError): pass 109class QuerySyntaxError(NotmuchError): pass 110 111class 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' 125