[PATCH] interpret Xapian errors from sdterr as exceptions

pazz patricktotzke at googlemail.com
Sat Jul 23 06:12:39 PDT 2011


This introduces globals.RaiseStderrErrors, a ContextManager
that raises error messages printed by libnotmuch to stderr
as NotmuchError(STATUS.XAPIAN_EXCEPTION, message=err).
---
 bindings/python/notmuch/database.py |    5 +++++
 bindings/python/notmuch/globals.py  |   24 ++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py
index 874087e..443980b 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -18,8 +18,10 @@ Copyright 2010 Sebastian Spaeth <Sebastian at SSpaeth.de>'
 """
 
 import os
+
 from ctypes import c_int, c_char_p, c_void_p, c_uint, c_long, byref
 from notmuch.globals import nmlib, STATUS, NotmuchError, Enum
+from notmuch.globals import RaiseStderrErrors
 from notmuch.thread import Threads
 from notmuch.message import Messages, Message
 from notmuch.tag import Tags
@@ -540,6 +542,9 @@ class Query(object):
         if query_p is None:
             NotmuchError(STATUS.NULL_POINTER)
         self._query = query_p
+        # ensure Xapian errors from stderr get raised if query syntax is bad
+        with RaiseStderrErrors():
+            Query._count_messages(self._query)
 
     def set_sort(self, sort):
         """Set the sort order future results will be delivered in
diff --git a/bindings/python/notmuch/globals.py b/bindings/python/notmuch/globals.py
index 77f2905..5e527ca 100644
--- a/bindings/python/notmuch/globals.py
+++ b/bindings/python/notmuch/globals.py
@@ -17,6 +17,10 @@ along with notmuch.  If not, see <http://www.gnu.org/licenses/>.
 Copyright 2010 Sebastian Spaeth <Sebastian at SSpaeth.de>'
 """
 
+import tempfile
+import sys
+import os
+
 from ctypes import CDLL, c_char_p, c_int
 from ctypes.util import find_library
 
@@ -98,3 +102,23 @@ class NotmuchError(Exception):
             return self.args[0]
         else:
             return STATUS.status2str(self.args[1])
+
+
+class RaiseStderrErrors:
+    def __enter__(self):
+        sys.stderr.flush()
+        (self.errfd, fn) = tempfile.mkstemp()
+        self.ferr = os.fdopen(self.errfd, 'r')
+        os.unlink(fn)
+        self.oldstderr = os.dup(sys.stderr.fileno())
+        os.dup2(self.errfd, sys.stderr.fileno())
+
+    def __exit__(self, *args):
+        sys.stderr.flush()
+        os.dup2(self.oldstderr, sys.stderr.fileno())
+        os.close(self.oldstderr)
+        os.lseek(self.errfd, 0, 0)
+        err = self.ferr.read()
+        if err:
+            raise NotmuchError(STATUS.XAPIAN_EXCEPTION, message=err)
+        self.ferr.close()
-- 
1.7.4.1



More information about the notmuch mailing list