mirror of
https://git.notmuchmail.org/git/notmuch
synced 2025-01-03 15:21:41 +01:00
python: rework creating of Subclasses
Add some smart magic, so that when we invoke a NotmuchError(STATUSVALUE), a nicely derived subclass is created, e.g. a OutOfMemoryError. This way users can easily distinguish between error types, while still catching NotmuchError. I have tested this, and hope it works for others too. Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
This commit is contained in:
parent
b6a01735d2
commit
8c51525e82
2 changed files with 35 additions and 21 deletions
|
@ -112,7 +112,7 @@ class Database(object):
|
||||||
def _assert_db_is_initialized(self):
|
def _assert_db_is_initialized(self):
|
||||||
"""Raises a NotmuchError in case self._db is still None"""
|
"""Raises a NotmuchError in case self._db is still None"""
|
||||||
if self._db is None:
|
if self._db is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NOT_INITIALIZED)
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
|
||||||
def create(self, path):
|
def create(self, path):
|
||||||
"""Creates a new notmuch database
|
"""Creates a new notmuch database
|
||||||
|
@ -231,7 +231,7 @@ class Database(object):
|
||||||
self._assert_db_is_initialized()
|
self._assert_db_is_initialized()
|
||||||
status = nmlib.notmuch_database_begin_atomic(self._db)
|
status = nmlib.notmuch_database_begin_atomic(self._db)
|
||||||
if status != STATUS.SUCCESS:
|
if status != STATUS.SUCCESS:
|
||||||
raise NotmuchError.get_subclass_exc(status)
|
raise NotmuchError(status)
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def end_atomic(self):
|
def end_atomic(self):
|
||||||
|
@ -253,7 +253,7 @@ class Database(object):
|
||||||
self._assert_db_is_initialized()
|
self._assert_db_is_initialized()
|
||||||
status = nmlib.notmuch_database_end_atomic(self._db)
|
status = nmlib.notmuch_database_end_atomic(self._db)
|
||||||
if status != STATUS.SUCCESS:
|
if status != STATUS.SUCCESS:
|
||||||
raise NotmuchError.get_subclass_exc(status)
|
raise NotmuchError(status)
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def get_directory(self, path):
|
def get_directory(self, path):
|
||||||
|
@ -284,7 +284,7 @@ class Database(object):
|
||||||
# we got an absolute path
|
# we got an absolute path
|
||||||
if not path.startswith(self.get_path()):
|
if not path.startswith(self.get_path()):
|
||||||
# but its initial components are not equal to the db path
|
# but its initial components are not equal to the db path
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.FILE_ERROR,
|
raise NotmuchError(STATUS.FILE_ERROR,
|
||||||
message="Database().get_directory() called "
|
message="Database().get_directory() called "
|
||||||
"with a wrong absolute path.")
|
"with a wrong absolute path.")
|
||||||
abs_dirpath = path
|
abs_dirpath = path
|
||||||
|
@ -355,7 +355,7 @@ class Database(object):
|
||||||
byref(msg_p))
|
byref(msg_p))
|
||||||
|
|
||||||
if not status in [STATUS.SUCCESS, STATUS.DUPLICATE_MESSAGE_ID]:
|
if not status in [STATUS.SUCCESS, STATUS.DUPLICATE_MESSAGE_ID]:
|
||||||
raise NotmuchError.get_subclass_exc(status)
|
raise NotmuchError(status)
|
||||||
|
|
||||||
#construct Message() and return
|
#construct Message() and return
|
||||||
msg = Message(msg_p, self)
|
msg = Message(msg_p, self)
|
||||||
|
@ -449,7 +449,7 @@ class Database(object):
|
||||||
self._assert_db_is_initialized()
|
self._assert_db_is_initialized()
|
||||||
tags_p = Database._get_all_tags(self._db)
|
tags_p = Database._get_all_tags(self._db)
|
||||||
if tags_p == None:
|
if tags_p == None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NULL_POINTER)
|
raise NotmuchError(STATUS.NULL_POINTER)
|
||||||
return Tags(tags_p, self)
|
return Tags(tags_p, self)
|
||||||
|
|
||||||
def create_query(self, querystring):
|
def create_query(self, querystring):
|
||||||
|
@ -573,13 +573,13 @@ class Query(object):
|
||||||
(too little memory)
|
(too little memory)
|
||||||
"""
|
"""
|
||||||
if db.db_p is None:
|
if db.db_p is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NOT_INITIALIZED)
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
# create reference to parent db to keep it alive
|
# create reference to parent db to keep it alive
|
||||||
self._db = db
|
self._db = db
|
||||||
# create query, return None if too little mem available
|
# create query, return None if too little mem available
|
||||||
query_p = Query._create(db.db_p, _str(querystr))
|
query_p = Query._create(db.db_p, _str(querystr))
|
||||||
if query_p is None:
|
if query_p is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NULL_POINTER)
|
raise NotmuchError(STATUS.NULL_POINTER)
|
||||||
self._query = query_p
|
self._query = query_p
|
||||||
|
|
||||||
def set_sort(self, sort):
|
def set_sort(self, sort):
|
||||||
|
@ -593,7 +593,7 @@ class Query(object):
|
||||||
been initialized.
|
been initialized.
|
||||||
"""
|
"""
|
||||||
if self._query is None:
|
if self._query is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NOT_INITIALIZED)
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
|
||||||
self.sort = sort
|
self.sort = sort
|
||||||
nmlib.notmuch_query_set_sort(self._query, sort)
|
nmlib.notmuch_query_set_sort(self._query, sort)
|
||||||
|
@ -619,7 +619,7 @@ class Query(object):
|
||||||
* :attr:`STATUS`.NULL_POINTER if search_threads failed
|
* :attr:`STATUS`.NULL_POINTER if search_threads failed
|
||||||
"""
|
"""
|
||||||
if self._query is None:
|
if self._query is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NOT_INITIALIZED)
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
|
||||||
threads_p = Query._search_threads(self._query)
|
threads_p = Query._search_threads(self._query)
|
||||||
|
|
||||||
|
@ -642,12 +642,12 @@ class Query(object):
|
||||||
* :attr:`STATUS`.NULL_POINTER if search_messages failed
|
* :attr:`STATUS`.NULL_POINTER if search_messages failed
|
||||||
"""
|
"""
|
||||||
if self._query is None:
|
if self._query is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NOT_INITIALIZED)
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
|
||||||
msgs_p = Query._search_messages(self._query)
|
msgs_p = Query._search_messages(self._query)
|
||||||
|
|
||||||
if msgs_p is None:
|
if msgs_p is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NULL_POINTER)
|
raise NotmuchError(STATUS.NULL_POINTER)
|
||||||
|
|
||||||
return Messages(msgs_p, self)
|
return Messages(msgs_p, self)
|
||||||
|
|
||||||
|
@ -667,7 +667,7 @@ class Query(object):
|
||||||
* :attr:`STATUS`.NOT_INITIALIZED if query is not inited
|
* :attr:`STATUS`.NOT_INITIALIZED if query is not inited
|
||||||
"""
|
"""
|
||||||
if self._query is None:
|
if self._query is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NOT_INITIALIZED)
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
|
||||||
return Query._count_messages(self._query)
|
return Query._count_messages(self._query)
|
||||||
|
|
||||||
|
@ -710,7 +710,7 @@ class Directory(object):
|
||||||
def _assert_dir_is_initialized(self):
|
def _assert_dir_is_initialized(self):
|
||||||
"""Raises a NotmuchError(:attr:`STATUS`.NOT_INITIALIZED) if dir_p is None"""
|
"""Raises a NotmuchError(:attr:`STATUS`.NOT_INITIALIZED) if dir_p is None"""
|
||||||
if self._dir_p is None:
|
if self._dir_p is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NOT_INITIALIZED)
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
|
||||||
def __init__(self, path, dir_p, parent):
|
def __init__(self, path, dir_p, parent):
|
||||||
"""
|
"""
|
||||||
|
@ -770,7 +770,7 @@ class Directory(object):
|
||||||
if status == STATUS.SUCCESS:
|
if status == STATUS.SUCCESS:
|
||||||
return
|
return
|
||||||
#fail with Exception otherwise
|
#fail with Exception otherwise
|
||||||
raise NotmuchError.get_subclass_exc(status)
|
raise NotmuchError(status)
|
||||||
|
|
||||||
def get_mtime(self):
|
def get_mtime(self):
|
||||||
"""Gets the mtime value of this directory in the database
|
"""Gets the mtime value of this directory in the database
|
||||||
|
@ -856,7 +856,7 @@ class Filenames(object):
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
if self._files_p is None:
|
if self._files_p is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NOT_INITIALIZED)
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
|
||||||
if not nmlib.notmuch_filenames_valid(self._files_p):
|
if not nmlib.notmuch_filenames_valid(self._files_p):
|
||||||
self._files_p = None
|
self._files_p = None
|
||||||
|
@ -879,7 +879,7 @@ class Filenames(object):
|
||||||
for file in files: print file
|
for file in files: print file
|
||||||
"""
|
"""
|
||||||
if self._files_p is None:
|
if self._files_p is None:
|
||||||
raise NotmuchError.get_subclass_exc(STATUS.NOT_INITIALIZED)
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
while nmlib.notmuch_filenames_valid(self._files_p):
|
while nmlib.notmuch_filenames_valid(self._files_p):
|
||||||
|
|
|
@ -96,7 +96,7 @@ class NotmuchError(Exception):
|
||||||
but SUCCESS has a corresponding subclassed Exception."""
|
but SUCCESS has a corresponding subclassed Exception."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_subclass_exc(cls, status, message=None):
|
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 = {
|
subclasses = {
|
||||||
STATUS.OUT_OF_MEMORY: OutOfMemoryError,
|
STATUS.OUT_OF_MEMORY: OutOfMemoryError,
|
||||||
|
@ -112,9 +112,23 @@ class NotmuchError(Exception):
|
||||||
STATUS.NOT_INITIALIZED: NotInitializedError
|
STATUS.NOT_INITIALIZED: NotInitializedError
|
||||||
}
|
}
|
||||||
assert 0 < status <= len(subclasses)
|
assert 0 < status <= len(subclasses)
|
||||||
return subclasses[status](status, message)
|
return subclasses[status]
|
||||||
|
|
||||||
def __init__(self, status, message=None):
|
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.status = status
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
||||||
|
@ -127,7 +141,7 @@ class NotmuchError(Exception):
|
||||||
return 'Unknown error'
|
return 'Unknown error'
|
||||||
|
|
||||||
# List of Subclassed exceptions that correspond to STATUS values and are
|
# List of Subclassed exceptions that correspond to STATUS values and are
|
||||||
# subclasses of NotmuchError:
|
# subclasses of NotmuchError.
|
||||||
class OutOfMemoryError(NotmuchError):
|
class OutOfMemoryError(NotmuchError):
|
||||||
pass
|
pass
|
||||||
class ReadOnlyDatabaseError(NotmuchError):
|
class ReadOnlyDatabaseError(NotmuchError):
|
||||||
|
|
Loading…
Reference in a new issue