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@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@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