diff options
| author | David Bremner <david@tethera.net> | 2016-06-28 16:48:30 +0200 |
|---|---|---|
| committer | David Bremner <david@tethera.net> | 2016-06-28 16:48:30 +0200 |
| commit | 7fe91ddc4f47170724d455e84d5d262410d569f2 (patch) | |
| tree | 4ba841df17c181ab6a785d408c4e5f8316bda9c1 /bindings/python | |
| parent | 148ceed198f98524db8482e212804c5a510d696b (diff) | |
| parent | ea5caecec5c50833a6f5a422e217a71eee6324af (diff) | |
Merge tag 'debian/0.22-1' into jessie-backports
notmuch Debian 0.22-1 upload (same as 0.22)
Diffstat (limited to 'bindings/python')
| -rw-r--r-- | bindings/python/README | 80 | ||||
| -rw-r--r-- | bindings/python/docs/source/filesystem.rst | 6 | ||||
| -rw-r--r-- | bindings/python/docs/source/status_and_errors.rst | 6 | ||||
| -rw-r--r-- | bindings/python/docs/source/threads.rst | 8 | ||||
| -rw-r--r-- | bindings/python/notmuch/__init__.py | 3 | ||||
| -rw-r--r-- | bindings/python/notmuch/compat.py | 4 | ||||
| -rw-r--r-- | bindings/python/notmuch/database.py | 22 | ||||
| -rw-r--r-- | bindings/python/notmuch/errors.py | 21 | ||||
| -rw-r--r-- | bindings/python/notmuch/filenames.py | 23 | ||||
| -rw-r--r-- | bindings/python/notmuch/globals.py | 5 | ||||
| -rw-r--r-- | bindings/python/notmuch/query.py | 27 | ||||
| -rw-r--r-- | bindings/python/notmuch/threads.py | 29 | ||||
| -rw-r--r-- | bindings/python/notmuch/version.py | 2 |
13 files changed, 97 insertions, 139 deletions
diff --git a/bindings/python/README b/bindings/python/README index e27ede2c..b20ae071 100644 --- a/bindings/python/README +++ b/bindings/python/README @@ -1,5 +1,5 @@ -notmuch -- The python interface to notmuch.so -============================================== +notmuch -- The python interface to notmuch +========================================== This module makes the functionality of the notmuch library (`http://notmuchmail.org`_) available to python. Successful import of @@ -10,78 +10,8 @@ If you have downloaded the full source tarball, you can create the documentation with sphinx installed, go to the docs directory and "make html". A static version of the documentation is available at: -http://packages.python.org/notmuch/ + https://notmuch.readthedocs.org/projects/notmuch-python/ -The current source code is being hosted at -http://bitbucket.org/spaetz/cnotmuch which also provides an issue -tracker, and release downloads. This package is tracked by the python -package index repository at `http://pypi.python.org/pypi/notmuch`_ and can thus be installed on a user's computer easily via "sudo easy_install notmuch" (you will still need to install the notmuch shared library separately as it is not included in this package). +To build the python bindings, do -The original source has been provided by (c)Sebastian Spaeth, 2010. -All code is available under the GNU GPLv3+ (see docs/COPYING) unless specified otherwise. - - -INSTALLATION & DEINSTALL ------------------------- - -The notmuch python module is available on pypi.python.org. This means -you can do "easy_install notmuch" on your linux box and it will get -installed into: - -/usr/local/lib/python2.x/dist-packages/ - -For uninstalling, you'll need to remove the "notmuch-0.4-py2.x.egg" -(or similar) directory and delete one entry in the "easy-install.pth" -file in that directory. - -It needs to have a libnotmuch.so or libnotmuch.so.1 available in some -library folder or will raise an exception when loading. -"OSError: libnotmuch.so.1: cannot open shared object file: No such file or directory" - - -Usage ------ -For more examples of how to use the notmuch interface, have a look at the -notmuch "binary" and the generated documentation. - -Example session: ->>>import notmuch ->>>db = notmuch.Database("/home/spaetz/mail") -db.get_path() -'/home/spaetz/mail' ->>>tags = db.get_all_tags() ->>>for tag in tags: ->>> print tag -inbox -... -maildir::draft -#--------------------------------------------- - -q = notmuch.Query(db,'from:Sebastian') -count = len(q.search_messages()) -1300 - -#--------------------------------------------- - ->>>db = notmuch.Database("/home/spaetz/mailHAHA") -NotmuchError: Could not open the specified database - -#--------------------------------------------- - ->>>tags = notmuch.Database("/home/spaetz/mail").get_all_tags() ->>>del(tags) - - -Building for a Debian package ------------------------------- -dpkg-buildpackage -i"\.hg|\/build" - - -Changelog ---------- -0.1 First public release -0.1.1 Fixed Database.create_query() -0.2.0 Implemented Thread() and Threads() methods -0.2.1 Implemented the remaining API methods, notably Directory() and Filenames() -0.2.2 Bug fixes -0.3.0 Incorporated in the notmuchmail.org git repository
\ No newline at end of file + python setup.py install --prefix=path/to/your/preferred/location diff --git a/bindings/python/docs/source/filesystem.rst b/bindings/python/docs/source/filesystem.rst index 4eb78107..a23ae41a 100644 --- a/bindings/python/docs/source/filesystem.rst +++ b/bindings/python/docs/source/filesystem.rst @@ -8,7 +8,11 @@ Files and directories .. autoclass:: Filenames - .. automethod:: Filenames.__len__ + .. method:: Filenames.__len__ + .. warning:: + :meth:`__len__` was removed in version 0.22 as it exhausted the + iterator and broke list(Filenames()). Use `len(list(names))` + instead. :class:`Directoy` -- A directory entry in the database ------------------------------------------------------ diff --git a/bindings/python/docs/source/status_and_errors.rst b/bindings/python/docs/source/status_and_errors.rst index dd6e31f8..68913f16 100644 --- a/bindings/python/docs/source/status_and_errors.rst +++ b/bindings/python/docs/source/status_and_errors.rst @@ -47,5 +47,11 @@ The following exceptions are all directly derived from NotmuchError. Each of the :members: .. autoexception:: UnbalancedAtomicError(message=None) :members: +.. autoexception:: UnsupportedOperationError(message=None) + :members: +.. autoexception:: UpgradeRequiredError(message=None) + :members: +.. autoexception:: PathError(message=None) + :members: .. autoexception:: NotInitializedError(message=None) :members: diff --git a/bindings/python/docs/source/threads.rst b/bindings/python/docs/source/threads.rst index e5a8c8a9..4324ac82 100644 --- a/bindings/python/docs/source/threads.rst +++ b/bindings/python/docs/source/threads.rst @@ -5,6 +5,10 @@ .. autoclass:: Threads - .. automethod:: __len__ + .. method:: __len__ + .. warning:: + :meth:`__len__` was removed in version 0.22 as it exhausted the + iterator and broke list(Threads()). Use `len(list(msgs))` + instead. - .. automethod:: __str__ +.. automethod:: __str__ diff --git a/bindings/python/notmuch/__init__.py b/bindings/python/notmuch/__init__.py index 5561624e..29416a5b 100644 --- a/bindings/python/notmuch/__init__.py +++ b/bindings/python/notmuch/__init__.py @@ -75,6 +75,9 @@ from .errors import ( UnbalancedFreezeThawError, UnbalancedAtomicError, NotInitializedError, + UnsupportedOperationError, + UpgradeRequiredError, + PathError, ) from .version import __VERSION__ __LICENSE__ = "GPL v3+" diff --git a/bindings/python/notmuch/compat.py b/bindings/python/notmuch/compat.py index adc8d244..daa268c1 100644 --- a/bindings/python/notmuch/compat.py +++ b/bindings/python/notmuch/compat.py @@ -65,3 +65,7 @@ else: raise TypeError('Expected str, got %s' % type(value)) return value.encode('utf-8', 'replace') + +# We import the SafeConfigParser class on behalf of other code to cope +# with the differences between Python 2 and 3. +SafeConfigParser # avoid warning about unused import diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py index 5b58e099..f3045334 100644 --- a/bindings/python/notmuch/database.py +++ b/bindings/python/notmuch/database.py @@ -36,7 +36,6 @@ from .errors import ( NotmuchError, NullPointerError, NotInitializedError, - ReadOnlyDatabaseError, ) from .message import Message from .tag import Tags @@ -484,7 +483,10 @@ class Database(object): removed. """ self._assert_db_is_initialized() - return self._remove_message(self._db, _str(filename)) + status = self._remove_message(self._db, _str(filename)) + if status not in [STATUS.SUCCESS, STATUS.DUPLICATE_MESSAGE_ID]: + raise NotmuchError(status) + return status def find_message(self, msgid): """Returns a :class:`Message` as identified by its message ID @@ -575,6 +577,22 @@ class Database(object): """ return Query(self, querystring) + """notmuch_database_status_string""" + _status_string = nmlib.notmuch_database_status_string + _status_string.argtypes = [NotmuchDatabaseP] + _status_string.restype = c_char_p + + def status_string(self): + """Returns the status string of the database + + This is sometimes used for additional error reporting + """ + self._assert_db_is_initialized() + s = Database._status_string(self._db) + if s: + return s.decode('utf-8', 'ignore') + return s + def __repr__(self): return "'Notmuch DB " + self.get_path() + "'" diff --git a/bindings/python/notmuch/errors.py b/bindings/python/notmuch/errors.py index f153a9c5..abca51d7 100644 --- a/bindings/python/notmuch/errors.py +++ b/bindings/python/notmuch/errors.py @@ -56,6 +56,9 @@ STATUS = Status(['SUCCESS', 'TAG_TOO_LONG', 'UNBALANCED_FREEZE_THAW', 'UNBALANCED_ATOMIC', + 'UNSUPPORTED_OPERATION', + 'UPGRADE_REQUIRED', + 'PATH_ERROR', '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 @@ -73,6 +76,9 @@ description. * TAG_TOO_LONG * UNBALANCED_FREEZE_THAW * UNBALANCED_ATOMIC + * UNSUPPORTED_OPERATION + * UPGRADE_REQUIRED + * PATH_ERROR * NOT_INITIALIZED Invoke the class method `notmuch.STATUS.status2str` with a status value as @@ -101,6 +107,9 @@ class NotmuchError(Exception, Python3StringMixIn): STATUS.TAG_TOO_LONG: TagTooLongError, STATUS.UNBALANCED_FREEZE_THAW: UnbalancedFreezeThawError, STATUS.UNBALANCED_ATOMIC: UnbalancedAtomicError, + STATUS.UNSUPPORTED_OPERATION: UnsupportedOperationError, + STATUS.UPGRADE_REQUIRED: UpgradeRequiredError, + STATUS.PATH_ERROR: PathError, STATUS.NOT_INITIALIZED: NotInitializedError, } assert 0 < status <= len(subclasses) @@ -175,6 +184,18 @@ class UnbalancedAtomicError(NotmuchError): status = STATUS.UNBALANCED_ATOMIC +class UnsupportedOperationError(NotmuchError): + status = STATUS.UNSUPPORTED_OPERATION + + +class UpgradeRequiredError(NotmuchError): + status = STATUS.UPGRADE_REQUIRED + + +class PathError(NotmuchError): + status = STATUS.PATH_ERROR + + class NotInitializedError(NotmuchError): """Derived from NotmuchError, this occurs if the underlying data structure (e.g. database is not initialized (yet) or an iterator has diff --git a/bindings/python/notmuch/filenames.py b/bindings/python/notmuch/filenames.py index 229f414d..f8f383e4 100644 --- a/bindings/python/notmuch/filenames.py +++ b/bindings/python/notmuch/filenames.py @@ -19,7 +19,6 @@ Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de> from ctypes import c_char_p from .globals import ( nmlib, - NotmuchMessageP, NotmuchFilenamesP, Python3StringMixIn, ) @@ -48,7 +47,7 @@ class Filenames(Python3StringMixIn): as well as:: - number_of_names = len(names) + list_of_names = list(names) and even a simple:: @@ -123,28 +122,10 @@ class Filenames(Python3StringMixIn): return "\n".join(self) _destroy = nmlib.notmuch_filenames_destroy - _destroy.argtypes = [NotmuchMessageP] + _destroy.argtypes = [NotmuchFilenamesP] _destroy.restype = None def __del__(self): """Close and free the notmuch filenames""" if self._files_p: self._destroy(self._files_p) - - def __len__(self): - """len(:class:`Filenames`) returns the number of contained files - - .. note:: - - This method exhausts the iterator object, so you will not be able to - iterate over them again. - """ - if not self._files_p: - raise NotInitializedError() - - i = 0 - while self._valid(self._files_p): - self._move_to_next(self._files_p) - i += 1 - self._files_p = None - return i diff --git a/bindings/python/notmuch/globals.py b/bindings/python/notmuch/globals.py index 70cfdc3d..6872a291 100644 --- a/bindings/python/notmuch/globals.py +++ b/bindings/python/notmuch/globals.py @@ -33,6 +33,11 @@ except: from .compat import Python3StringMixIn, encode_utf8 as _str +# We import these on behalf of other modules. Silence warning about +# these symbols not being used. +Python3StringMixIn +_str + class Enum(object): """Provides ENUMS as "code=Enum(['a','b','c'])" where code.a=0 etc...""" def __init__(self, names): diff --git a/bindings/python/notmuch/query.py b/bindings/python/notmuch/query.py index 378aa47d..43270072 100644 --- a/bindings/python/notmuch/query.py +++ b/bindings/python/notmuch/query.py @@ -28,6 +28,7 @@ from .globals import ( NotmuchMessagesP, ) from .errors import ( + NotmuchError, NullPointerError, NotInitializedError, ) @@ -133,10 +134,10 @@ class Query(object): self._assert_query_is_initialized() self._exclude_tag(self._query, _str(tagname)) - """notmuch_query_search_threads""" - _search_threads = nmlib.notmuch_query_search_threads - _search_threads.argtypes = [NotmuchQueryP] - _search_threads.restype = NotmuchThreadsP + """notmuch_query_search_threads_st""" + _search_threads_st = nmlib.notmuch_query_search_threads_st + _search_threads_st.argtypes = [NotmuchQueryP, POINTER(NotmuchThreadsP)] + _search_threads_st.restype = c_uint def search_threads(self): """Execute a query for threads @@ -153,16 +154,19 @@ class Query(object): :raises: :exc:`NullPointerError` if search_threads failed """ self._assert_query_is_initialized() - threads_p = Query._search_threads(self._query) + threads_p = NotmuchThreadsP() # == NULL + status = Query._search_threads_st(self._query, byref(threads_p)) + if status != 0: + raise NotmuchError(status) if not threads_p: raise NullPointerError return Threads(threads_p, self) - """notmuch_query_search_messages""" - _search_messages = nmlib.notmuch_query_search_messages - _search_messages.argtypes = [NotmuchQueryP] - _search_messages.restype = NotmuchMessagesP + """notmuch_query_search_messages_st""" + _search_messages_st = nmlib.notmuch_query_search_messages_st + _search_messages_st.argtypes = [NotmuchQueryP, POINTER(NotmuchMessagesP)] + _search_messages_st.restype = c_uint def search_messages(self): """Filter messages according to the query and return @@ -172,7 +176,10 @@ class Query(object): :raises: :exc:`NullPointerError` if search_messages failed """ self._assert_query_is_initialized() - msgs_p = Query._search_messages(self._query) + msgs_p = NotmuchMessagesP() # == NULL + status = Query._search_messages_st(self._query, byref(msgs_p)) + if status != 0: + raise NotmuchError(status) if not msgs_p: raise NullPointerError diff --git a/bindings/python/notmuch/threads.py b/bindings/python/notmuch/threads.py index f8ca34a9..a550523f 100644 --- a/bindings/python/notmuch/threads.py +++ b/bindings/python/notmuch/threads.py @@ -46,7 +46,7 @@ class Threads(Python3StringMixIn): as well as:: - number_of_msgs = len(threads) + list_of_threads = list(threads) will "exhaust" the threads. If you need to re-iterate over a list of messages you will need to retrieve a new :class:`Threads` object. @@ -64,8 +64,7 @@ class Threads(Python3StringMixIn): for thread in threads: threadlist.append(thread) - # threads is "exhausted" now and even len(threads) will raise an - # exception. + # threads is "exhausted" now. # However it will be kept around until all retrieved Thread() objects are # also deleted. If you did e.g. an explicit del(threads) here, the # following lines would fail. @@ -132,30 +131,6 @@ class Threads(Python3StringMixIn): return thread next = __next__ # python2.x iterator protocol compatibility - def __len__(self): - """len(:class:`Threads`) returns the number of contained Threads - - .. note:: As this iterates over the threads, we will not be able to - iterate over them again! So this will fail:: - - #THIS FAILS - threads = Database().create_query('').search_threads() - if len(threads) > 0: #this 'exhausts' threads - # next line raises :exc:`NotInitializedError`!!! - for thread in threads: print thread - """ - if not self._threads: - raise NotInitializedError() - - i = 0 - # returns 'bool'. On out-of-memory it returns None - while self._valid(self._threads): - self._move_to_next(self._threads) - i += 1 - # reset self._threads to mark as "exhausted" - self._threads = None - return i - def __nonzero__(self): ''' Implement truth value testing. If __nonzero__ is not diff --git a/bindings/python/notmuch/version.py b/bindings/python/notmuch/version.py index db9d0764..c1d472be 100644 --- a/bindings/python/notmuch/version.py +++ b/bindings/python/notmuch/version.py @@ -1,3 +1,3 @@ # this file should be kept in sync with ../../../version -__VERSION__ = '0.21' +__VERSION__ = '0.22' SOVERSION = '4' |
