From a7561cc20b17669784c3259afcbcef98029f93e9 Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Thu, 23 Feb 2012 00:11:22 +0100 Subject: [PATCH 1/1] python: move the exception classes into error.py Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de> --- bindings/python/notmuch/__init__.py | 4 +- bindings/python/notmuch/database.py | 14 +- bindings/python/notmuch/directory.py | 6 +- bindings/python/notmuch/errors.py | 183 +++++++++++++++++++++++++++ bindings/python/notmuch/filenames.py | 6 +- bindings/python/notmuch/globals.py | 160 +---------------------- bindings/python/notmuch/message.py | 10 +- bindings/python/notmuch/messages.py | 6 +- bindings/python/notmuch/query.py | 2 + bindings/python/notmuch/tag.py | 4 +- bindings/python/notmuch/thread.py | 6 +- bindings/python/notmuch/threads.py | 6 +- 12 files changed, 225 insertions(+), 182 deletions(-) create mode 100644 bindings/python/notmuch/errors.py diff --git a/bindings/python/notmuch/__init__.py b/bindings/python/notmuch/__init__.py index fddc492a..5561624e 100644 --- a/bindings/python/notmuch/__init__.py +++ b/bindings/python/notmuch/__init__.py @@ -60,8 +60,8 @@ from .query import Query from .tag import Tags from .thread import Thread from .threads import Threads -from .globals import ( - nmlib, +from .globals import nmlib +from .errors import ( STATUS, NotmuchError, OutOfMemoryError, diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py index 800264b7..44d40fdb 100644 --- a/bindings/python/notmuch/database.py +++ b/bindings/python/notmuch/database.py @@ -22,12 +22,6 @@ import codecs from ctypes import c_char_p, c_void_p, c_uint, byref, POINTER from notmuch.globals import ( nmlib, - STATUS, - FileError, - NotmuchError, - NullPointerError, - NotInitializedError, - ReadOnlyDatabaseError, Enum, _str, NotmuchDatabaseP, @@ -35,6 +29,14 @@ from notmuch.globals import ( NotmuchMessageP, NotmuchTagsP, ) +from .errors import ( + STATUS, + FileError, + NotmuchError, + NullPointerError, + NotInitializedError, + ReadOnlyDatabaseError, +) from notmuch.message import Message from notmuch.tag import Tags from .query import Query diff --git a/bindings/python/notmuch/directory.py b/bindings/python/notmuch/directory.py index b679aa29..0c5e015e 100644 --- a/bindings/python/notmuch/directory.py +++ b/bindings/python/notmuch/directory.py @@ -20,11 +20,13 @@ Copyright 2010 Sebastian Spaeth ' from ctypes import c_uint, c_long from notmuch.globals import ( nmlib, + NotmuchDirectoryP, + NotmuchFilenamesP +) +from .errors import ( STATUS, NotmuchError, NotInitializedError, - NotmuchDirectoryP, - NotmuchFilenamesP ) from .filenames import Filenames diff --git a/bindings/python/notmuch/errors.py b/bindings/python/notmuch/errors.py new file mode 100644 index 00000000..f153a9c5 --- /dev/null +++ b/bindings/python/notmuch/errors.py @@ -0,0 +1,183 @@ +""" +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 . + +Copyright 2010 Sebastian Spaeth +""" + +from ctypes import c_char_p, c_int + +from .globals import ( + nmlib, + Enum, + Python3StringMixIn, +) + +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 (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 unicode(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, 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 + but SUCCESS has a corresponding subclassed Exception.""" + + @classmethod + def get_exc_subclass(cls, status): + """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] + + def __new__(cls, *args, **kwargs): + """Return a correct subclass of NotmuchError if needed + + We return a NotmuchError instance if status is None (or 0) and a + subclass that inherits from NotmuchError depending on the + 'status' parameter otherwise.""" + # get 'status'. Passed in as arg or kwarg? + status = args[0] if len(args) else kwargs.get('status', None) + # 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? + return subclass.__new__(subclass, *args, **kwargs) + + def __init__(self, status=None, message=None): + self.status = status + self.message = message + + def __unicode__(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): + 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 + been exhausted. You can test for NotmuchError with .status = + STATUS.NOT_INITIALIZED""" + status = STATUS.NOT_INITIALIZED diff --git a/bindings/python/notmuch/filenames.py b/bindings/python/notmuch/filenames.py index 232a9eda..12050df9 100644 --- a/bindings/python/notmuch/filenames.py +++ b/bindings/python/notmuch/filenames.py @@ -19,12 +19,14 @@ Copyright 2010 Sebastian Spaeth ' from ctypes import c_char_p from notmuch.globals import ( nmlib, - NullPointerError, - NotInitializedError, NotmuchMessageP, NotmuchFilenamesP, Python3StringMixIn, ) +from .errors import ( + NullPointerError, + NotInitializedError, +) class Filenames(Python3StringMixIn): diff --git a/bindings/python/notmuch/globals.py b/bindings/python/notmuch/globals.py index 41384604..442f3e35 100644 --- a/bindings/python/notmuch/globals.py +++ b/bindings/python/notmuch/globals.py @@ -17,7 +17,7 @@ along with notmuch. If not, see . Copyright 2010 Sebastian Spaeth ' """ import sys -from ctypes import CDLL, c_char_p, c_int, Structure, POINTER +from ctypes import CDLL, Structure, POINTER #----------------------------------------------------------------------------- #package-global instance of the notmuch library @@ -66,164 +66,6 @@ class Enum(object): 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 (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 unicode(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, 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 - but SUCCESS has a corresponding subclassed Exception.""" - - @classmethod - def get_exc_subclass(cls, status): - """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] - - def __new__(cls, *args, **kwargs): - """Return a correct subclass of NotmuchError if needed - - We return a NotmuchError instance if status is None (or 0) and a - subclass that inherits from NotmuchError depending on the - 'status' parameter otherwise.""" - # get 'status'. Passed in as arg or kwarg? - status = args[0] if len(args) else kwargs.get('status', None) - # 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? - return subclass.__new__(subclass, *args, **kwargs) - - def __init__(self, status=None, message=None): - self.status = status - self.message = message - - def __unicode__(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): - 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 - been exhausted. You can test for NotmuchError with .status = - STATUS.NOT_INITIALIZED""" - status = STATUS.NOT_INITIALIZED - - class NotmuchDatabaseS(Structure): pass NotmuchDatabaseP = POINTER(NotmuchDatabaseS) diff --git a/bindings/python/notmuch/message.py b/bindings/python/notmuch/message.py index d17b9bc6..9eb4feef 100644 --- a/bindings/python/notmuch/message.py +++ b/bindings/python/notmuch/message.py @@ -26,15 +26,17 @@ from .globals import ( Enum, _str, Python3StringMixIn, - STATUS, - NotmuchError, - NullPointerError, - NotInitializedError, NotmuchTagsP, NotmuchMessageP, NotmuchMessagesP, NotmuchFilenamesP, ) +from .errors import ( + STATUS, + NotmuchError, + NullPointerError, + NotInitializedError, +) from .tag import Tags from .filenames import Filenames diff --git a/bindings/python/notmuch/messages.py b/bindings/python/notmuch/messages.py index 20d36329..d94f91b4 100644 --- a/bindings/python/notmuch/messages.py +++ b/bindings/python/notmuch/messages.py @@ -20,12 +20,14 @@ Copyright 2010 Sebastian Spaeth ' from .globals import ( nmlib, - NullPointerError, - NotInitializedError, NotmuchTagsP, NotmuchMessageP, NotmuchMessagesP, ) +from .errors import ( + NullPointerError, + NotInitializedError, +) from .tag import Tags from .message import Message diff --git a/bindings/python/notmuch/query.py b/bindings/python/notmuch/query.py index fcd67e5c..ddaf8e08 100644 --- a/bindings/python/notmuch/query.py +++ b/bindings/python/notmuch/query.py @@ -26,6 +26,8 @@ from notmuch.globals import ( NotmuchThreadsP, NotmuchDatabaseP, NotmuchMessagesP, +) +from .errors import ( NullPointerError, NotInitializedError, ) diff --git a/bindings/python/notmuch/tag.py b/bindings/python/notmuch/tag.py index 526e51cd..711bf533 100644 --- a/bindings/python/notmuch/tag.py +++ b/bindings/python/notmuch/tag.py @@ -20,9 +20,11 @@ from ctypes import c_char_p from notmuch.globals import ( nmlib, Python3StringMixIn, + NotmuchTagsP, +) +from .errors import ( NullPointerError, NotInitializedError, - NotmuchTagsP, ) diff --git a/bindings/python/notmuch/thread.py b/bindings/python/notmuch/thread.py index 0dac522c..a759c909 100644 --- a/bindings/python/notmuch/thread.py +++ b/bindings/python/notmuch/thread.py @@ -20,12 +20,14 @@ Copyright 2010 Sebastian Spaeth ' from ctypes import c_char_p, c_long, c_int from notmuch.globals import ( nmlib, - NullPointerError, - NotInitializedError, NotmuchThreadP, NotmuchMessagesP, NotmuchTagsP, ) +from .errors import ( + NullPointerError, + NotInitializedError, +) from .messages import Messages from notmuch.tag import Tags from datetime import date diff --git a/bindings/python/notmuch/threads.py b/bindings/python/notmuch/threads.py index 9d305e23..690206ef 100644 --- a/bindings/python/notmuch/threads.py +++ b/bindings/python/notmuch/threads.py @@ -20,11 +20,13 @@ Copyright 2010 Sebastian Spaeth ' from notmuch.globals import ( nmlib, Python3StringMixIn, - NullPointerError, - NotInitializedError, NotmuchThreadP, NotmuchThreadsP, ) +from .errors import ( + NullPointerError, + NotInitializedError, +) from .thread import Thread class Threads(Python3StringMixIn): -- 2.43.0