Re: xapian exceptions not caught in python bindings?

Subject: Re: xapian exceptions not caught in python bindings?

Date: Sat, 23 Jul 2011 14:36:02 +0100

To: David Bremner

Cc: Patrick Totzke,

From: Patrick Totzke

Hi all,

I hope the patch I send is correctly formated, I'm still fumbling with
git send-email and the --in-reply-to option.
Anyhow, forgive my language, of course I didn't mean to be condescending in any
way by calling these prints garbage! It's just that it's highly unusual and very
'non-pythonic' that a module directly prints to stderr instead of raising exceptions
and if you work directly with a curseslike interface on a terminal these
errormessages litter my screen.

The patch I send is a suggestion how to fix the behaviour described in my last post.
It introduces a ContextManager class that can be used to raise messages from stderr
as Xapian exceptions like this:

> from notmuch.globals import RaiseStderrErrors
> with RaiseStderrErrors():
>  do_stuff()

Now, if one executes: 
> from notmuch import Database
> bad_querystring = "test AND"
> query = Database().create_query(bad_querystring
one gets a nice Xapian exception
  File "", line 4, in <module>
    query = Database().create_query(bad_querystring)
  File "/usr/local/lib/python2.7/dist-packages/notmuch/", line 432, in create_query
    return Query(self, querystring)
  File "/usr/local/lib/python2.7/dist-packages/notmuch/", line 514, in __init__
    self.create(db, querystr)
  File "/usr/local/lib/python2.7/dist-packages/notmuch/", line 547, in create
  File "/usr/local/lib/python2.7/dist-packages/notmuch/", line 123, in __exit__
    raise NotmuchError(STATUS.XAPIAN_EXCEPTION, message=err)
notmuch.globals.NotmuchError: A Xapian exception occurred: Syntax: <expression> AND <expression>
Query string was: test AND

There are two problems with this suggestion however.
First, one needs to redirect sdterr to a tempfile: Using StringIO doesn't work since
just replacing sys.stderr with something else is not "low level" enough, the messages will
still get printed. An alternative is using os.dup2, which replaces the file descriptor
of stderr directly, but cStringIO objects dont have .fileno()..
see [0,1].
The second problem is, that creating a query object with a malformed querystring doesn't
print anything to stderr, only if you use that object errors get printed (notmuch/lib/
Thus, I call count_messages() once after initialising a new notmuch.databas.Query object (at the end of  Query.create). This ensures that Query.__init__() raises an exception when given bad 
querystrings, but at the cost of triggering an unnecessary count_messages().



On Sun, Jul 17, 2011 at 04:51:41PM -0300, David Bremner wrote:
> On Sun, 17 Jul 2011 20:35:38 +0100, Patrick Totzke <> wrote:
> > If you run the following snippet, you notice that not only do we get
> > xapian-garbage on stderr but we don't really get any exceptions at the
> > position where it would make sense:
> I wouldn't call that "xapian-garbage" since it is output from
> libnotmuch.
> d
signature.asc (application/pgp-signature)