* [PATCH] SWIG bindings
@ 2010-01-26 3:53 Ben Gamari
2010-01-26 3:53 ` [PATCH] Add SWIG interface file Ben Gamari
0 siblings, 1 reply; 4+ messages in thread
From: Ben Gamari @ 2010-01-26 3:53 UTC (permalink / raw)
To: notmuch
Hey all,
Here's the latest version of my patch adding SWIG interface generation to
notmuch. It has been rebased on the shared-library patches I sent over earlier
this week, so you'll need those as well. Unfortunately, SWIG has effectively no
support for exposing notmuch's C-style object-oriented interface in a
reasonable manner. Therefore, I use SWIG to generate a set of low-level
bindings which is then wrapped with a light-weight module properly exposing the
functions in their intended class structure. This seems like a fairly good
solution, given the wide variety of capabilities possessed by modern high-level
languages.
As you can see, it all works quite nicely,
[2252 ben@ben-laptop swig(swig)] $ python
Python 2.6.4 (r264:75706, Dec 7 2009, 18:43:55)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from notmuch import Database
>>> db=Database.open('/home/ben/.mail', Database.MODE_READ_ONLY)
>>> for tag in db.get_all_tags(): print tag
...
attachment
inbox
unread
Let me know what you think. Thanks!
- Ben
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] Add SWIG interface file
2010-01-26 3:53 [PATCH] SWIG bindings Ben Gamari
@ 2010-01-26 3:53 ` Ben Gamari
2010-01-26 5:38 ` Ben Gamari
0 siblings, 1 reply; 4+ messages in thread
From: Ben Gamari @ 2010-01-26 3:53 UTC (permalink / raw)
To: notmuch
---
swig/Makefile | 18 ++++
swig/notmuch.py | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++
swig/notmuch_funcs.i | 9 ++
3 files changed, 249 insertions(+), 0 deletions(-)
create mode 100644 swig/Makefile
create mode 100644 swig/notmuch.py
create mode 100644 swig/notmuch_funcs.i
diff --git a/swig/Makefile b/swig/Makefile
new file mode 100644
index 0000000..7b10ea7
--- /dev/null
+++ b/swig/Makefile
@@ -0,0 +1,18 @@
+include ../Makefile.config
+
+INCLUDES=-I../lib -I/usr/include/python2.6
+CFLAGS=${INCLUDES}
+
+all : python
+
+python : _notmuch_funcs.so notmuch.py
+
+_notmuch_funcs.so : notmuch_funcs_wrap.o
+ g++ -shared -lnotmuch ${XAPIAN_LDFLAGS} ${GMIME_LDFLAGS} ${TALLOC_LDFLAGS} -o $@ $<
+
+%_wrap.o : %_wrap.c
+ gcc ${CFLAGS} -fPIC -c -o $@ $<
+
+%_wrap.c %.py : %.i
+ swig -python ${INCLUDES} $<
+
diff --git a/swig/notmuch.py b/swig/notmuch.py
new file mode 100644
index 0000000..e17f71f
--- /dev/null
+++ b/swig/notmuch.py
@@ -0,0 +1,222 @@
+import notmuch_funcs as nm
+from datetime import datetime
+
+class Exception(Exception):
+ def get_message():
+ errors = {
+ nm.NOTMUCH_STATUS_OUT_OF_MEMORY: 'out of memory',
+ nm.NOTMUCH_STATUS_READONLY_DATABASE: 'database opened as read-only',
+ nm.NOTMUCH_STATUS_XAPIAN_EXCEPTION: 'xapian error',
+ nm.NOTMUCH_STATUS_FILE_ERROR: 'file error',
+ nm.NOTMUCH_STATUS_FILE_NOT_EMAIL: 'file not email message',
+ nm.NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: 'duplicate message id',
+ nm.NOTMUCH_STATUS_NULL_POINTER: 'null pointer',
+ nm.NOTMUCH_STATUS_TAG_TOO_LONG: 'tag name too long',
+ nm.NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: 'unbalanced freeze/thaw',
+ }
+ return errors.get(self.status, 'unknown error')
+
+ def __init__(self, status):
+ self.status = status
+
+def _handle_status(status):
+ if (status != nm.NOTMUCH_STATUS_SUCCESS):
+ raise Exception(status)
+
+class Database(object):
+ MODE_READ_ONLY = nm.NOTMUCH_DATABASE_MODE_READ_ONLY
+ MODE_READ_WRITE = nm.NOTMUCH_DATABASE_MODE_READ_WRITE
+
+ def __init__(self, db):
+ if not db:
+ raise Exception("Failed to open database")
+ self.db = db
+
+ @staticmethod
+ def create(path):
+ return Database(nm.notmuch_database_create(path))
+
+ @staticmethod
+ def open(path, mode):
+ return Database(nm.notmuch_database_open(path, mode))
+
+ def close(self):
+ nm.notmuch_database_close(self.db)
+
+ def get_path(self):
+ return nm.notmuch_database_get_path(self.db)
+
+ def set_timestamp(self, key, timestamp):
+ _handle_status(nm.notmuch_database_set_timestamp(self.db, key, timestamp))
+
+ def get_timestamp(self, key):
+ return datetime.fromtimestamp(nm.notmuch_database_get_timestamp(self.db, key))
+
+ def add_message(self, filename, message):
+ _handle_status(nm.notmuch_database_add_message(self.db, filename, message.message))
+
+ def find_message(self, message_id):
+ return Message(nm.notmuch_database_find_message(self.db, message_id))
+
+ def get_all_tags(self):
+ return Tags(nm.notmuch_database_get_all_tags(self.db))
+
+ def __destroy__(self):
+ self.close()
+
+class Query(object):
+ def __init__(self, db, query_string):
+ self.query = nm.notmuch_query_create(db, query_string)
+ if not self.query: # This might not work
+ raise "Failed to create query"
+
+ def set_sort(self, sort):
+ nm.notmuch_query_set_sort(self.query, sort)
+
+ def search_threads(self):
+ return Threads(nm.notmuch_query_search_threads(self.query))
+
+ def search_messages(self):
+ return Messages(nm.notmuch_query_search_messages(self.query))
+
+ def count_message(self):
+ return nm.notmuch_query_count_messages(self.query)
+
+ def __destroy__(self):
+ nm.notmuch_query_destroy(self.query)
+
+class Tags(object):
+ def __init__(self, tags):
+ self.tags = tags
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if not nm.notmuch_tags_has_more(self.tags):
+ raise StopIteration
+ else:
+ h = nm.notmuch_tags_get(self.tags)
+ nm.notmuch_tags_advance(self.tags)
+ return h
+
+ def __destroy__(self):
+ nm.notmuch_messages_destroy(self.tags)
+
+class Thread(object):
+ def __init__(self, thread):
+ self.thread = thread
+
+ def get_thread_id(self):
+ return nm.notmuch_thread_get_thread_id(self.thread)
+
+ def get_total_messages(self):
+ return nm.notmuch_thread_total_messages(self.thread)
+
+ def get_toplevel_messages(self):
+ return Messages(nm.notmuch_thread_get_toplevel_messages(self.thread))
+
+ def get_matched_messages(self):
+ return nm.notmuch_thread_get_matched_messages(self.thread)
+
+ def get_authors(self):
+ return nm.notmuch_thread_get_authors(self.thread)
+
+ def get_subject(self):
+ return nm.notmuch_thread_get_subject(self.thread)
+
+ def get_oldest_date(self):
+ return nm.notmuch_thread_get_oldest_date(self.thread)
+
+ def get_newest_date(self):
+ return nm.notmuch_thread_get_newest_date(self.thread)
+
+ def get_tags(self):
+ return Tags(nm.notmuch_thread_get_tags(self.thread))
+
+ def __destroy__(self):
+ nm.notmuch_thread_destroy(self.thread)
+
+class Threads(object):
+ def __init__(self, threads):
+ self.threads = threads
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if not nm.notmuch_threads_has_more(self.threads):
+ raise StopIteration
+ else:
+ h = Thread(nm.notmuch_threads_get(self.threads))
+ nm.notmuch_threads_advance(self.threads)
+ return h
+
+ def __destroy__(self):
+ nm.notmuch_threads_destroy(self.threads)
+
+class Messages(object):
+ def __init__(self, messages):
+ self.messages = messages
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if not nm.notmuch_messages_has_more(self.messages):
+ raise StopIteration
+ else:
+ h = Message(nm.notmuch_messages_get(self.messages))
+ nm.notmuch_messages_advance(self.messages)
+ return h
+
+ def __destroy__(self):
+ nm.notmuch_messages_destroy(self.messages)
+
+ def collect_tags(self):
+ return Tags(nm.notmuch_messages_collect_tags(self.messages))
+
+class Message(object):
+ def __init__(self, message):
+ self.message = message
+
+ def get_replies(self):
+ return Messages(nm.notmuch_message_get_replies(self.message))
+
+ def get_filename(self):
+ return nm.notmuch_message_get_filename(self.message)
+
+ def get_flag(self, flag):
+ return bool(nm.notmuch_message_get_flag(self.message, flag))
+
+ def set_flag(self, flag, value):
+ return nm.notmuch_message_set_flag(self.message, flag, value)
+
+ def get_date(self):
+ return datetime.fromtimestamp(nm.notmuch_message_get_date(self.message))
+
+ def get_header(self, header):
+ return nm.notmuch_message_get_header(self.message, header)
+
+ def get_tags(self):
+ return Tags(nm.notmuch_message_get_tags(self.message))
+
+ def add_tag(self, tag):
+ _handle_status(nm.notmuch_message_add_tag(self.message, tag))
+
+ def remove_tag(self, tag):
+ _handle_status(nm.notmuch_message_remove_tag(self.message, tag))
+
+ def remove_all_tags(self):
+ nm.notmuch_message_remove_all_tags(self.message)
+
+ def freeze(self):
+ nm.notmuch_message_freeze(self.message)
+
+ def thaw(self):
+ nm.notmuch_message_thaw(self.message)
+
+ def __destroy__(self):
+ nm.notmuch_message_destroy(self.message)
+
+
diff --git a/swig/notmuch_funcs.i b/swig/notmuch_funcs.i
new file mode 100644
index 0000000..cc1826e
--- /dev/null
+++ b/swig/notmuch_funcs.i
@@ -0,0 +1,9 @@
+%module notmuch_funcs
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "notmuch.h"
+%}
+
+%include "notmuch.h"
+
--
1.6.3.3
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] Add SWIG interface file
2010-01-26 3:53 ` [PATCH] Add SWIG interface file Ben Gamari
@ 2010-01-26 5:38 ` Ben Gamari
2010-01-26 6:15 ` [PATCH] Build and link against notmuch shared library Ben Gamari
0 siblings, 1 reply; 4+ messages in thread
From: Ben Gamari @ 2010-01-26 5:38 UTC (permalink / raw)
To: notmuch
For the record, both the swig branch and the shared-library branch are
available from,
anonymous: git://goldnerlab.physics.umass.edu/notmuch
gitweb: http://goldnerlab.physics.umass.edu/git?p=notmuch.git;a=summary
Hope this helps,
- Ben
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] Build and link against notmuch shared library
2010-01-26 5:38 ` Ben Gamari
@ 2010-01-26 6:15 ` Ben Gamari
0 siblings, 0 replies; 4+ messages in thread
From: Ben Gamari @ 2010-01-26 6:15 UTC (permalink / raw)
To: notmuch
Inger in #notmuch brought to light some build issues that will occur when the
notmuch binary is being built before libnotmuch is installed. Here is an
updated patch that resolves these issues.
---
.gitignore | 1 +
Makefile | 1 +
Makefile.local | 6 ++++--
lib/Makefile.local | 9 +++++----
4 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/.gitignore b/.gitignore
index efa98fb..daf8094 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ tags
.deps
notmuch
notmuch.1.gz
+libnotmuch.so*
*.[ao]
*~
.*.swp
diff --git a/Makefile b/Makefile
index 64b9d4a..6f296bb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,4 @@
+SONAME = libnotmuch.so.1
WARN_CXXFLAGS=-Wall -Wextra -Wwrite-strings -Wswitch-enum
WARN_CFLAGS=$(WARN_CXXFLAGS) -Wmissing-declarations
diff --git a/Makefile.local b/Makefile.local
index 04bac83..5b6af0a 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -21,8 +21,8 @@ notmuch_client_srcs = \
show-message.c
notmuch_client_modules = $(notmuch_client_srcs:.c=.o)
-notmuch: $(notmuch_client_modules) lib/notmuch.a
- $(call quiet,CXX,$(LDFLAGS)) $^ $(FINAL_LDFLAGS) -o $@
+notmuch: $(notmuch_client_modules) lib/libnotmuch.so
+ $(call quiet,CC,$(LDFLAGS)) -Llib -lnotmuch $(filter-out lib/libnotmuch.so,$^) $(FINAL_LDFLAGS) -o $@
notmuch.1.gz: notmuch.1
$(call quiet,gzip) --stdout $^ > $@
@@ -33,6 +33,8 @@ install: all notmuch.1.gz
install -d $$d ; \
done ;
install notmuch $(DESTDIR)$(prefix)/bin/
+ install lib/$(SONAME) $(DESTDIR)$(prefix)/lib/
+ ln -sf $(DESTDIR)$(prefix)/lib/$(SONAME) $(DESTDIR)$(prefix)/lib/libnotmuch.so
install -m0644 notmuch.1.gz $(DESTDIR)$(prefix)/share/man/man1/
install-emacs: install emacs
diff --git a/lib/Makefile.local b/lib/Makefile.local
index 70489e1..a6462ae 100644
--- a/lib/Makefile.local
+++ b/lib/Makefile.local
@@ -1,5 +1,5 @@
dir=lib
-extra_cflags += -I$(dir)
+extra_cflags += -I$(dir) -fPIC
libnotmuch_c_srcs = \
$(dir)/libsha1.c \
@@ -18,8 +18,9 @@ libnotmuch_cxx_srcs = \
$(dir)/thread.cc
libnotmuch_modules = $(libnotmuch_c_srcs:.c=.o) $(libnotmuch_cxx_srcs:.cc=.o)
-$(dir)/notmuch.a: $(libnotmuch_modules)
- $(call quiet,AR) rcs $@ $^
+$(dir)/libnotmuch.so : $(libnotmuch_modules)
+ $(call quiet,CXX,$(LDFLAGS)) $^ $(FINAL_LDFLAGS) -shared -Wl,-soname=$(SONAME) -o $@
+ ln -sf $(SONAME) $@
SRCS := $(SRCS) $(libnotmuch_c_srcs) $(libnotmuch_cxx_srcs)
-CLEAN := $(CLEAN) $(libnotmuch_modules) $(dir)/notmuch.a
+CLEAN := $(CLEAN) $(libnotmuch_modules) $(dir)/libnotmuch.so *.so
--
1.6.3.3
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-01-26 6:16 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-26 3:53 [PATCH] SWIG bindings Ben Gamari
2010-01-26 3:53 ` [PATCH] Add SWIG interface file Ben Gamari
2010-01-26 5:38 ` Ben Gamari
2010-01-26 6:15 ` [PATCH] Build and link against notmuch shared library Ben Gamari
Code repositories for project(s) associated with this public inbox
https://yhetil.org/notmuch.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).