Put each libnotmuch function reference right in front of the
corresponding python wrapper.
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
Rename Database.__del__ to Database.close, move it just below the open
function and call close() in a newly created destructor just below the
constructor.
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
Before 3434d1940 the return values of libnotmuch functions were
declared as c_void_p and the code checking for errors compared the
returned value to None, which is the ctypes equivalent of a NULL
pointer.
But said commit wrapped all the data types in python classes and the
semantic changed in a subtle way. If a function returns NULL, the
wrapped python value is falsish, but no longer equal to None.
Backported from master to 0.11.
Before 3434d1940 the return values of libnotmuch functions were
declared as c_void_p and the code checking for errors compared the
returned value to None, which is the ctypes equivalent of a NULL
pointer.
But said commit wrapped all the data types in python classes and the
semantic changed in a subtle way. If a function returns NULL, the
wrapped python value is falsish, but no longer equal to None.
All strings are unicode strings in python 3 and the basestring and
unicode types are removed hence the need for a specialized version.
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
Recent changes introduced lots of unicodification of strings, mostly in
the form of .decode('utf-8', errors='ignore'). However, python 2.5 does
not like the errors keyword argument and complains. It does work when
used as a simple arg though, so that's what this patch does.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Formerly Message.get_replies() returned an iterator or None forcing
users to check the result before iterating over it leading to strange
looking code at the call site.
Fix this flaw by adding an EmptyMessagesResult class that behaves like
the Messages class but immediatly raises StopIteration if used as an
iterator and returning objects of this type from Message.get_replies()
to indicate that there are no replies.
Since 2b01161191, Message.__str__ doesn't
construct a hash containing the thread data before
constructing the formatstring. This changes the formatstring
to accept positional parameters instead of a hash.
Now that types are checked correctly, we also need to make sure that all the
arguments actually are instances of these types. Otherwise the function calls
will fail and raise an exception similar to this one:
ctypes.ArgumentError: argument 3: <type 'exceptions.TypeError'>: expected
LP_LP_NotmuchMessageS instance instead of pointer to c_void_p
We were not returning anything at all, which does not match the API
documentation. Fixed. Thanks to Patrick Totzke for the heads up.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Add type information to the ctypes._FuncPtr wrappers and
use the wrapper classes instead of c_void_p for pointers
to notmuch_*_t.
This enables the ctypes library to type check parameters
being handed to functions from the notmuch library.
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
Technically, this is a superfluous change, as the self.status variable
currently gets set in NotmuchErrors's __new__ function. However, in the
long run I would like to get rid of the weird __new__ implementation which
might be somewhat confusing for users (NotmuchError(status) returns a
different class, e.g. OutOfMemoryError)
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Remove code duplication by using the new helper function. Also raise the
new fine grained exceptions in many cases, rather than the more generic
NotmuchErrors.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Catch up with the major version bump. I wonder if this could somehow be
automatically made the correct version number. Oh well, I hope it
doesn't change too often :-).
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Two new wrappers:
Notmuch::Database.find_message(id) => Notmuch::Message or nil
Notmuch::Database.find_message_by_filename(path) => Notmuch::Message or nil
Previously, the Filenames generator only yielded *one* filename before
returning, making Message.get_filenames() behave as Message.get_filename(). This
commit fixes this incorrect behavior: now the generator yields all the
filenames, as expected.
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>
To make the exception handling more effective in code using the
python bindings it is necessary to differentiate between the
different kind of failures.
Add an exception class for each status code and add a decode
classmethod to the NotmuchError class that acts as a factory.
Import the new classes in __init__.py so they can be easily
imported by anyone.
Patch modifed by Sebastian Spaeth.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
1) Fix added .gitignore from commit dc8a1745 to work on the docs folder
2) Improve in-code developer documentation to produce better
sphinx-generated documentation. No code changes.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
There are various locations where exceptions are constructed but
not raised. This patch adds the necessary raise statements.
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
Raising Exception is considered bad since the only way to catch
it is to do 'except Exception'. Raising a TypeError is more
appropriate.
Since the format parameter has already been validated, checking
it again is not necessary. Simplify this conditional.
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
Rename the function to clarify its effect and remove all the comments
accompanying each call to the function.
Modified by Sebastian Spaeth to apply cleanly again and remove some
blank lines.
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Rename the function to clarify its effect and remove all the comments
accompanying each call to the function.
Modified slightly by Sebastian Spaeth to catch all new instances and
remove some blank lines too.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
Passing None to STATUS.status2str raises an ArgumentError. Add a
check for this case and provide a generic message.
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
Providing exception objects with meaningful attribute names
is much nicer than using e.args[].
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
The line 'notmuch' in the toplevel .gitignore file is to broad
and matches bindings/python/notmuch making it cumbersome to
git-add files within that directory.
Refine the toplevel file to only match the generated notmuch
executable and add a more specialized .gitignore file to the
python directory.
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
* Add UNBALANCED_ATOMIC status code
Catch up with the notmuch status codes, and add the UNBALANCED_ATOMIC
one.
* Add the begin_atomic and end_atomic calls to libnotmuch
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
According to the common Ruby function naming convention, potentially
dangerous functions or functions which operate on the object itself are
suffixed with an exclamation mark. Both of these are true for object
destroying functions.
The following modules are affected:
- Notmuch::Directory
- Notmuch::FileNames
- Notmuch::Query
- Notmuch::Threads
- Notmuch::Thread
- Notmuch::Messages
- Notmuch::Message
- Notmuch::Tags
If we use unicode objects, libnotmuch would not cope with null bytes in
the byte array, so we need to make sure they are nicely formatted as
utf-8.
Introduce a helper function _str which does this throughout the code.
Patch slightly modified by Sebastian Spaeth.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
we now have three files to keep in sync. That seems wrong, but I guess
we will live with it for now.
The main problem is that the python code is distributed separately, so
it can't get the version from 'version'.
The choice ~rcX is for convenience with debian versioning.
Decode and Encode from/to unicode objects as required to be able to take
unicode path names. Previously we would error out when an unicode object
were handed it.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Importing the notmuch module in setup.py is a no-no, and we want
to auto-generate the version number in the release process.
Outsource __VERSION__ to the new version.py which contains nothing else
and which can therefor easily be autogenerated. Have setup.py read in
the file via execfile and test if importing the version number actually
worked.
This should make all happy.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
This reverts commit 8826fc2d7b.
It seems that importing the module in setup.py is controversial at best,
as it will fail for users that don't have all dependencies
installed. This was the case in e.g. the Ubuntu autobuilder, so building
notmuch failed. The plan is to create an autogenerated setup.py that can
be used for version information.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
We were using a template setup.py which parsed __init__.py in complex
ways just to find out the version number. Simply import notmuch and use
__VERSION__ directly. Also adapt some wording and setup.py values while
going through.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
This prevents unsafe calls to decode for return value None in
get_authors/get_subject which would current throw an Exception. Original
patch modified by Sebastian Spaeth.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
len() exhausts the tag iterator and e.g. list() or "".join(tags)
implicitly call len() if existing and then failing. So, we remove
Tags.__len__().
If you need to know the number of tags a message has, do use
len(list(tags)). It would be nicer to be able to support len() directly...
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
If we try to pull a non-existing tag, Tags._get will return None and the
appended .decode() command will fail. So make sure that there is a tag to
be fetched before fetching it.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
In case, search_threads returns an error we are supposed to throw an
Exception. But we did not "raise" it, this was an oversight and this
commit fixes it.
There is still the problem that there is often output to stderr by
libnotmuch detailing the xapian error and this is simply printed
out. But this requires fixing at the libnotmuch level...
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Rather than returning simply strings and having to guess their encoding,
return explicit unicode() strings for the tags. Xapian stores UTF8, so
we know that they come as UTF8 encoded string.
Note: I tried to directly use the c_wchar_p type of the ctypes library
which translates directly into an unicode type, but that did not work
out so well, so we take c_char_p and .decode() them manually.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
If we pass in an unicode instance as query string, we would probably get
weird behavior (and indeed do so, see mail
id:"20110707113700.GA16347@megatron"). If a unicode instance is passed
in, make sure we encode it properly to an utf-8 encoded byte string.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
A stupid typo was preventing this from ever working and it was not
detected until now. Patrick noted the typo and proposed the fix in mail
id:"20110704203926.GA20238@brick.lan".
Patch-by: Patrick Totzke <patricktotzke@googlemail.com>
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
In order to remain consistent with the underlying C API, we do not
automatically synchronize notmuch tags and maildir flags anymore.
The underlying functions Message.maildir_flags_to_tags and
Message.tags_to_maildir_flags still exist and are available to the user.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Importing notmuch loads the notmuch shared library. When building
without a system install of notmuch, this requires e.g. setting
LD_LIBRARY_PATH for building and fails completely for cleaning.
We were still using len(self.get_replies()) for the __str__ summary of a
mail, but 1) len(Messages()) has just gone away 2) the number of replies
can not be retrieved when we got the message via search_messages()
anyway, and 3) it is likely quite expensive to pull all replies for all
messages that we display a summary of.
So we fix this by simplifying str(Message()) to omit the number of replies.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
libnotmuch (and python) crashed when I accidently passed in an invalid
value as path argument to the Database() instantiation.
Therefore, we now check via assert that the handed in path is actually a
real string (or None).
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
and also maildir_flags_to_tags. The methods will be invoked by
db.add_message() and also (if not overridden via function parameter) by
add|remove_tag and remove_all_tags. Documentation on the usage has been
updated.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Improve the documentation with regard to the new __cmp__ and __hash__
methods and the implications of doing set arithmetic with Messages()
objects.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
We can now do: if msg1 == msg2, and we can use set arithmetic on
Messages():
s1, s2= msgs1, msgs2
s1.union(s2)
s2 -= s1
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Messages.__len__() exhausted the iterator and list() inherently calls
len(), so we could not invoke list(msgs) without getting errors. Fix
this by implementing __nonzero__ but removing __len__ on Messages.
Use Query.count_messages() or len(list(msgs)) if you need to know the
number.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
To match the upcoming release, and with the updated API to match the
current libnotmuch, bump the python version number (notmuch.__VERSION__)
to 0.6.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Analog to Threads.__nonzero__ this allows us to perform list() on a Threads() object and to repeatedly call "if Tags():" or "bool(Tags())" without implicitly invoking len(), thus exhausting our iterator.
While touching this code, I added a small micro-optimization to the Tag next() function. There is no need to explicitly check _is_valid, as _get implicitly does check for validness and returns None, if there is no more Tag to fetch. This avoids some roundtrips into the library when iterating through Tags.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
__nonzero__ checks if Threads() contains at least one more valid thread
The existence of this function makes 'if Threads(): foo' work, as that
previously implicitely called len() exhausting the iterator. This
function makes `bool(Threads())` work repeatedly.
For further info, see http://docs.python.org/reference/datamodel.html.
Credits for the hint go to Brian May.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
They had accidentally been left out, so we should also include the
function docs for get_messages in the API docs.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Message().get_filenames() will return a generator that allows to
iterator over the recorded filenames for a certain Message. Do ntoe that
as all generators, these are one-time use only. You will have to reget
them to perform various actions. So this works::
len(Message().get_filenames())
list(Message().get_filenames())
for n in Message().get_filenames():
print n
But this won't::
names = Message().get_filenames()
len(names) #uses up the iterator
list(names) #outch, already used up...
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
The old instructions were telling users to do "easy_install cnotmuch"
which installed some old, stale bindings. The new instructions should
be much more effective.
Convert the meta information to point to the notmuchmail.org repository, rather
than the old cnotmuch location. I will delete the "cnotmuch" package
from http://pypi.python.org/pypi/cnotmuch and create a new "notmuch"
package there that contains the current versions.
Also bump the version number to 0.4. I will need to upgrade the API
first before I can release the 0.5 of the bindings, there are still some
methods missing.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Let the user destroy objects that she wants explicitly.
It's not possible to specify the order objects are garbage collected.
See id:86y6f8v838.fsf@harikalardiyari.ev on ruby-talk for more
information.
Database.find_message() used to be able to reliably indicate whether a
message exists or not (in which case it returns None). However, the
recent API change of the notmuch library means we will return None
even for all Xapian exceptions, which happens e.g. when the current
Database has been modified by another project. Therefore the return
value of None cannot be reliably be used to indicate whether a message
exists or not. Make the docs state that explicitely.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
No more .hg files needed in the git repo.
No stock notmuch-test suite needed in a subdirectory.
We have the real one in this repository
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>