From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id Nzu1NLOQul/oSQAA0tVLHw (envelope-from ) for ; Sun, 22 Nov 2020 16:24:19 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2 with LMTPS id UAVNMLOQul9iKAAAB5/wlQ (envelope-from ) for ; Sun, 22 Nov 2020 16:24:19 +0000 Received: from mail.notmuchmail.org (nmbug.tethera.net [IPv6:2607:5300:201:3100::1657]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (2048 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id E3C6994051E for ; Sun, 22 Nov 2020 16:24:18 +0000 (UTC) Received: from nmbug.tethera.net (localhost [127.0.0.1]) by mail.notmuchmail.org (Postfix) with ESMTP id B385328C1D; Sun, 22 Nov 2020 11:24:10 -0500 (EST) Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by mail.notmuchmail.org (Postfix) with ESMTPS id 2C1F528BE1 for ; Sun, 22 Nov 2020 11:24:07 -0500 (EST) Received: by mail-ej1-x62b.google.com with SMTP id 7so19920267ejm.0 for ; Sun, 22 Nov 2020 08:24:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Apes8/Vs/LXqUvAc/PPODfewgzeFdoAnBhoqwX7wRyA=; b=CxY2vcEr5Q0EuIiRrcDjl03U3NWdfXRP/sOI88MA8xCtF9+5rbjc90qt5nMXERGIj6 oYV16eAENUzZvhxIXrPfKIULxfZ7U4Uil4Cvo0NsvJGZSlqRUl+FTpiSVsUNC5VpYA/S OYjYOWKO5LsVqtN+XjuP7ld6Bdui4Mjwp6PzouJbMTl28FyO+9yyhQ7qa/PxywFOVKA9 tI0iGFPZzv+3pozhkijuH/RY58Sf7afQjcZ7fdjE8bxbTbyWRX9AyKPyBRVKOO9xMn1p M9XIAm4h3gbkV5MEabYlojoa/uQsvGeUq5VeJAAhZ+wPiLqsTwrIaptykbS8VnQ44YrG 0Nkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=Apes8/Vs/LXqUvAc/PPODfewgzeFdoAnBhoqwX7wRyA=; b=Q9jnzSWXsM4y0Kd9aKee/ccKB6wO988CvA98GML2BRku97fVIbUN6wD8xUAgqtwP/l NmKXuwZIANvwpoW0rOTLjXhjVpX6prJRuYiEY8cb6LyTuPP002141itRiYSZQps2Rwzt n/2xy2prDeVedxXvIOyWhwkRcGoYkOF3oTp3K1g08L52pB1qzDNnALygYlsoYI36dlYe l7u2CoAqRW3sj+uB1TFP94U33OIF/OqJ9SkFTEL/13pKeaIzf/iCF5KwuCVVNpdR5XPd mYQ2wfw4QUpshAoSdeC0WYUv+4N0PLygMxqolXKUoVIp/cgS4nAQjgCb7lxipclEUHWj kFow== X-Gm-Message-State: AOAM530H9dCClrqpLXpaOIicQ++por8dIB53Hi4lCysFQxRb8AMnLPoq yUtyk5A5SCdIrlS0J9f7ToZtelV9/H4= X-Google-Smtp-Source: ABdhPJxeNMcEWBK64MIgevr8grGchGAHODGUHHirrX9qlAK/4zGfciZMTNK4EqtE0LDNejzYQBL9ag== X-Received: by 2002:a17:906:22d9:: with SMTP id q25mr2758273eja.29.1606062245064; Sun, 22 Nov 2020 08:24:05 -0800 (PST) Received: from powell.devork.be (2a02-8388-8480-1180-4c18-fc69-8d8c-22b5.cable.dynamic.v6.surfer.at. [2a02:8388:8480:1180:4c18:fc69:8d8c:22b5]) by smtp.gmail.com with ESMTPSA id d14sm3761925edu.63.2020.11.22.08.24.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 22 Nov 2020 08:24:04 -0800 (PST) Sender: Floris Bruynooghe Received: (nullmailer pid 64537 invoked by uid 1000); Sun, 22 Nov 2020 16:24:03 -0000 From: Floris Bruynooghe To: notmuch@notmuchmail.org Cc: Floris Bruynooghe Subject: [PATCH] python-cffi: Extract cdefs from notmuch.h Date: Sun, 22 Nov 2020 17:23:53 +0100 Message-Id: <20201122162353.63824-2-flub@devork.be> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201122162353.63824-1-flub@devork.be> References: <20201122162353.63824-1-flub@devork.be> MIME-Version: 1.0 Message-ID-Hash: XQC4OMDE6PHYYLMBIR7AAZ6BQC6H6Y6N X-Message-ID-Hash: XQC4OMDE6PHYYLMBIR7AAZ6BQC6H6Y6N X-MailFrom: floris.bruynooghe@gmail.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-notmuch.notmuchmail.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.1 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Scanner: ns3122888.ip-94-23-21.eu Authentication-Results: aspmx1.migadu.com; dkim=fail (body hash did not verify) header.d=gmail.com header.s=20161025 header.b=CxY2vcEr; dmarc=none; spf=pass (aspmx1.migadu.com: domain of notmuch-bounces@notmuchmail.org designates 2607:5300:201:3100::1657 as permitted sender) smtp.mailfrom=notmuch-bounces@notmuchmail.org X-Spam-Score: 0.99 X-TUID: D1bbeXvmJ1Dx Instead of having all the required cdefs copied in _build.py this uses the C pre-compiler to extract them from notmuch.h itself. To do this we need to indroduce a few more #ifdefs in the header file since the CFFI parser can not deal with everything the real C parser can deal with, plus it does not want to see symbols not from notmuch. The main downside is that we always compile in all symbols of the library, not just those used. Furthermore to avoid having lots of compiler warnings about deprecated symbols this excludes all unused deprecated functions using even more #ifdefs. To allow this to work this also makes sure that when using the Makefile to build notmuch the python bindings find and use the headers and library from the build directory, before it would still link against the system-wide libnotmuch.so.5. I have not tested this with out-of tree builds. --- .gitignore | 2 + bindings/Makefile.local | 8 +- bindings/python-cffi/README | 63 ++++ bindings/python-cffi/notmuch2/_build.py | 359 +++------------------ bindings/python-cffi/pip-editable-build.sh | 16 + lib/notmuch.h | 20 +- 6 files changed, 159 insertions(+), 309 deletions(-) create mode 100644 bindings/python-cffi/README create mode 100755 bindings/python-cffi/pip-editable-build.sh diff --git a/.gitignore b/.gitignore index 3edd1768..ddc0f650 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ /.stamps /Makefile.config /bindings/python-cffi/build/ +/bindings/python-cffi/notmuch2/*.c +/bindings/python-cffi/notmuch2/*.so /lib/libnotmuch*.dylib /lib/libnotmuch.so* /notmuch diff --git a/bindings/Makefile.local b/bindings/Makefile.local index bc960bbc..7523a0b5 100644 --- a/bindings/Makefile.local +++ b/bindings/Makefile.local @@ -16,7 +16,13 @@ endif python-cffi-bindings: lib/$(LINKER_NAME) ifeq ($(HAVE_PYTHON3_CFFI),1) cd $(dir)/python-cffi && \ - ${PYTHON} setup.py build --build-lib build/stage && \ + ${PYTHON} setup.py build_ext \ + --build-lib build/stage \ + --include-dirs ../../lib \ + --library-dirs ../../lib \ + --rpath $(CURDIR)/lib && \ + ${PYTHON} setup.py build \ + --build-lib build/stage && \ mkdir -p build/stage/tests && cp tests/*.py build/stage/tests endif diff --git a/bindings/python-cffi/README b/bindings/python-cffi/README new file mode 100644 index 00000000..2f20e17f --- /dev/null +++ b/bindings/python-cffi/README @@ -0,0 +1,63 @@ +notmuch2 - python3 compatible bindings to notmuch + +These bindings use CFFI to generate the bindings making it work well +with both CPython and PyPy. They try to ensure all operations +from within Python are safe and handle the memory management themselves. + +Building notmuch2 +----------------- + +The provided setup.py file can be used to build and install the +bindings. You will need python3, setuptools and cffi installed for +this to work. + +By default this will assume that the C compiler can find both +notmuch.h and libnotmuch.so.5, if these are installed in a system-wide +location they will normally be found there. When building notmuch +with make it will ensure that the C compiler finds the in-tree version +of notmuch instead of any system-wide one which might be available. +However the resulting python module is not relocatable and is mainly +used by the notmuch test suite. For installing your own notmuch +python package it is recommended to first install libnotmuch system +wide and than use setup.py to build and install the python package. + +If you really need to customise your build environment, have a look at +the INCUDE_DIRS, LIBRARY_DIRS and EXTRA_LINK_ARGS variables in +notmuch2/_build.py. + +Documentation +------------- + +The package has extensive docstrings, these docs are also included in +the general notmuch sphinx documentation. See the notmuch `doc/` +subdirectory for this. + + +Development +----------- + +An easy way to work on the bindings themselves is to create a +virtualenv to work in. Install the python bindings in editable mode +using: + +$ cd bindings/python-cffi +$ pip install -e . + +However as described above this will build against the system-wide +notmuch installation. If you need to work on the currently developed +libnotmuch you can invoke pip with some extra --global-option +arguments. This is rather verbose, so the pip-editable-build.sh +script does this for you: + +$ make +$ cd bindings/python-cffi +$ ./pip-editable-build.sh + +Tests are written using pytest and can be run using: + +$ pip install pytest pytest-cov +$ pytest + +Individual tests can be selected: + +$ pytest tests/test_database.py::TestCreate::test_create \ No newline at end of file diff --git a/bindings/python-cffi/notmuch2/_build.py b/bindings/python-cffi/notmuch2/_build.py index f269f2a1..e9c446f6 100644 --- a/bindings/python-cffi/notmuch2/_build.py +++ b/bindings/python-cffi/notmuch2/_build.py @@ -1,9 +1,55 @@ +import distutils.ccompiler +import distutils.log +import distutils.sysconfig +import os +import shutil +import tempfile + import cffi +# Also look in these directories for include files, i.e. notmuch.h (-I) +INCLUDE_DIRS = ["../../lib"] + +# Also look in these directories for libraries, i.e. libnotmuch.so.5 (-L) +LIBRARY_DIRS = ["../../lib"] + +# Add extra linker flags, e.g. -Wl,--enable-new-dtags,-R/path/to/notmuch/libdir +EXTRA_LINK_ARGS = ["-Wl,--enable-new-dtags,-R/home/flub/Projects/notmuch/lib"] + + +def extract_functions(): + """Extract the function definitions from notmuch.h. + + This creates a .h file with a single `#include ` line + in it. It then runs the C preprocessor with the PY_CFFI symbol + defined to create an output file which contains all function + definitions found in `notmuch.h`. + """ + distutils.log.set_verbosity(distutils.log.INFO) + cc = distutils.ccompiler.new_compiler(force=True) + distutils.sysconfig.customize_compiler(cc) + tmpdir = tempfile.mkdtemp() + try: + src_name = os.path.join(tmpdir, "include.h") + dst_name = os.path.join(tmpdir, "expanded.h") + with open(src_name, "w") as src_fp: + src_fp.write("#include ") + cc.preprocess( + source=src_name, + output_file=dst_name, + include_dirs=INCLUDE_DIRS, + macros=[("PY_CFFI", "1")], + ) + with open(dst_name, "r") as dst_fp: + return dst_fp.read() + finally: + shutil.rmtree(tmpdir) + + ffibuilder = cffi.FFI() ffibuilder.set_source( - 'notmuch2._capi', + "notmuch2._capi", r""" #include #include @@ -16,9 +62,10 @@ ffibuilder.set_source( #ERROR libnotmuch version < 5.1 not supported #endif """, - include_dirs=['../../lib'], - library_dirs=['../../lib'], - libraries=['notmuch'], + include_dirs=INCLUDE_DIRS, + library_dirs=LIBRARY_DIRS, + extra_link_args=EXTRA_LINK_ARGS, + libraries=["notmuch"], ) ffibuilder.cdef( r""" @@ -30,310 +77,10 @@ ffibuilder.cdef( #define LIBNOTMUCH_MICRO_VERSION ... #define NOTMUCH_TAG_MAX ... - - typedef enum _notmuch_status { - NOTMUCH_STATUS_SUCCESS = 0, - NOTMUCH_STATUS_OUT_OF_MEMORY, - NOTMUCH_STATUS_READ_ONLY_DATABASE, - NOTMUCH_STATUS_XAPIAN_EXCEPTION, - NOTMUCH_STATUS_FILE_ERROR, - NOTMUCH_STATUS_FILE_NOT_EMAIL, - NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID, - NOTMUCH_STATUS_NULL_POINTER, - NOTMUCH_STATUS_TAG_TOO_LONG, - NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW, - NOTMUCH_STATUS_UNBALANCED_ATOMIC, - NOTMUCH_STATUS_UNSUPPORTED_OPERATION, - NOTMUCH_STATUS_UPGRADE_REQUIRED, - NOTMUCH_STATUS_PATH_ERROR, - NOTMUCH_STATUS_ILLEGAL_ARGUMENT, - NOTMUCH_STATUS_LAST_STATUS - } notmuch_status_t; - typedef enum { - NOTMUCH_DATABASE_MODE_READ_ONLY = 0, - NOTMUCH_DATABASE_MODE_READ_WRITE - } notmuch_database_mode_t; - typedef int notmuch_bool_t; - typedef enum _notmuch_message_flag { - NOTMUCH_MESSAGE_FLAG_MATCH, - NOTMUCH_MESSAGE_FLAG_EXCLUDED, - NOTMUCH_MESSAGE_FLAG_GHOST, - } notmuch_message_flag_t; - typedef enum { - NOTMUCH_SORT_OLDEST_FIRST, - NOTMUCH_SORT_NEWEST_FIRST, - NOTMUCH_SORT_MESSAGE_ID, - NOTMUCH_SORT_UNSORTED - } notmuch_sort_t; - typedef enum { - NOTMUCH_EXCLUDE_FLAG, - NOTMUCH_EXCLUDE_TRUE, - NOTMUCH_EXCLUDE_FALSE, - NOTMUCH_EXCLUDE_ALL - } notmuch_exclude_t; - typedef enum { - NOTMUCH_DECRYPT_FALSE, - NOTMUCH_DECRYPT_TRUE, - NOTMUCH_DECRYPT_AUTO, - NOTMUCH_DECRYPT_NOSTASH, - } notmuch_decryption_policy_t; - - // These are fully opaque types for us, we only ever use pointers. - typedef struct _notmuch_database notmuch_database_t; - typedef struct _notmuch_query notmuch_query_t; - typedef struct _notmuch_threads notmuch_threads_t; - typedef struct _notmuch_thread notmuch_thread_t; - typedef struct _notmuch_messages notmuch_messages_t; - typedef struct _notmuch_message notmuch_message_t; - typedef struct _notmuch_tags notmuch_tags_t; - typedef struct _notmuch_string_map_iterator notmuch_message_properties_t; - typedef struct _notmuch_directory notmuch_directory_t; - typedef struct _notmuch_filenames notmuch_filenames_t; - typedef struct _notmuch_config_list notmuch_config_list_t; - typedef struct _notmuch_indexopts notmuch_indexopts_t; - - const char * - notmuch_status_to_string (notmuch_status_t status); - - notmuch_status_t - notmuch_database_create_verbose (const char *path, - notmuch_database_t **database, - char **error_message); - notmuch_status_t - notmuch_database_create (const char *path, notmuch_database_t **database); - notmuch_status_t - notmuch_database_open_verbose (const char *path, - notmuch_database_mode_t mode, - notmuch_database_t **database, - char **error_message); - notmuch_status_t - notmuch_database_open (const char *path, - notmuch_database_mode_t mode, - notmuch_database_t **database); - notmuch_status_t - notmuch_database_close (notmuch_database_t *database); - notmuch_status_t - notmuch_database_destroy (notmuch_database_t *database); - const char * - notmuch_database_get_path (notmuch_database_t *database); - unsigned int - notmuch_database_get_version (notmuch_database_t *database); - notmuch_bool_t - notmuch_database_needs_upgrade (notmuch_database_t *database); - notmuch_status_t - notmuch_database_begin_atomic (notmuch_database_t *notmuch); - notmuch_status_t - notmuch_database_end_atomic (notmuch_database_t *notmuch); - unsigned long - notmuch_database_get_revision (notmuch_database_t *notmuch, - const char **uuid); - notmuch_status_t - notmuch_database_index_file (notmuch_database_t *database, - const char *filename, - notmuch_indexopts_t *indexopts, - notmuch_message_t **message); - notmuch_status_t - notmuch_database_remove_message (notmuch_database_t *database, - const char *filename); - notmuch_status_t - notmuch_database_find_message (notmuch_database_t *database, - const char *message_id, - notmuch_message_t **message); - notmuch_status_t - notmuch_database_find_message_by_filename (notmuch_database_t *notmuch, - const char *filename, - notmuch_message_t **message); - notmuch_tags_t * - notmuch_database_get_all_tags (notmuch_database_t *db); - - notmuch_query_t * - notmuch_query_create (notmuch_database_t *database, - const char *query_string); - const char * - notmuch_query_get_query_string (const notmuch_query_t *query); - notmuch_database_t * - notmuch_query_get_database (const notmuch_query_t *query); - void - notmuch_query_set_omit_excluded (notmuch_query_t *query, - notmuch_exclude_t omit_excluded); - void - notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort); - notmuch_sort_t - notmuch_query_get_sort (const notmuch_query_t *query); - notmuch_status_t - notmuch_query_add_tag_exclude (notmuch_query_t *query, const char *tag); - notmuch_status_t - notmuch_query_search_threads (notmuch_query_t *query, - notmuch_threads_t **out); - notmuch_status_t - notmuch_query_search_messages (notmuch_query_t *query, - notmuch_messages_t **out); - notmuch_status_t - notmuch_query_count_messages (notmuch_query_t *query, unsigned int *count); - notmuch_status_t - notmuch_query_count_threads (notmuch_query_t *query, unsigned *count); - void - notmuch_query_destroy (notmuch_query_t *query); - - notmuch_bool_t - notmuch_threads_valid (notmuch_threads_t *threads); - notmuch_thread_t * - notmuch_threads_get (notmuch_threads_t *threads); - void - notmuch_threads_move_to_next (notmuch_threads_t *threads); - void - notmuch_threads_destroy (notmuch_threads_t *threads); - - const char * - notmuch_thread_get_thread_id (notmuch_thread_t *thread); - notmuch_messages_t * - notmuch_message_get_replies (notmuch_message_t *message); - int - notmuch_thread_get_total_messages (notmuch_thread_t *thread); - notmuch_messages_t * - notmuch_thread_get_toplevel_messages (notmuch_thread_t *thread); - notmuch_messages_t * - notmuch_thread_get_messages (notmuch_thread_t *thread); - int - notmuch_thread_get_matched_messages (notmuch_thread_t *thread); - const char * - notmuch_thread_get_authors (notmuch_thread_t *thread); - const char * - notmuch_thread_get_subject (notmuch_thread_t *thread); - time_t - notmuch_thread_get_oldest_date (notmuch_thread_t *thread); - time_t - notmuch_thread_get_newest_date (notmuch_thread_t *thread); - notmuch_tags_t * - notmuch_thread_get_tags (notmuch_thread_t *thread); - void - notmuch_thread_destroy (notmuch_thread_t *thread); - - notmuch_bool_t - notmuch_messages_valid (notmuch_messages_t *messages); - notmuch_message_t * - notmuch_messages_get (notmuch_messages_t *messages); - void - notmuch_messages_move_to_next (notmuch_messages_t *messages); - void - notmuch_messages_destroy (notmuch_messages_t *messages); - notmuch_tags_t * - notmuch_messages_collect_tags (notmuch_messages_t *messages); - - const char * - notmuch_message_get_message_id (notmuch_message_t *message); - const char * - notmuch_message_get_thread_id (notmuch_message_t *message); - const char * - notmuch_message_get_filename (notmuch_message_t *message); - notmuch_filenames_t * - notmuch_message_get_filenames (notmuch_message_t *message); - notmuch_bool_t - notmuch_message_get_flag (notmuch_message_t *message, - notmuch_message_flag_t flag); - void - notmuch_message_set_flag (notmuch_message_t *message, - notmuch_message_flag_t flag, - notmuch_bool_t value); - time_t - notmuch_message_get_date (notmuch_message_t *message); - const char * - notmuch_message_get_header (notmuch_message_t *message, - const char *header); - notmuch_tags_t * - notmuch_message_get_tags (notmuch_message_t *message); - notmuch_status_t - notmuch_message_add_tag (notmuch_message_t *message, const char *tag); - notmuch_status_t - notmuch_message_remove_tag (notmuch_message_t *message, const char *tag); - notmuch_status_t - notmuch_message_remove_all_tags (notmuch_message_t *message); - notmuch_status_t - notmuch_message_maildir_flags_to_tags (notmuch_message_t *message); - notmuch_status_t - notmuch_message_tags_to_maildir_flags (notmuch_message_t *message); - notmuch_status_t - notmuch_message_freeze (notmuch_message_t *message); - notmuch_status_t - notmuch_message_thaw (notmuch_message_t *message); - notmuch_status_t - notmuch_message_get_property (notmuch_message_t *message, - const char *key, const char **value); - notmuch_status_t - notmuch_message_add_property (notmuch_message_t *message, - const char *key, const char *value); - notmuch_status_t - notmuch_message_remove_property (notmuch_message_t *message, - const char *key, const char *value); - notmuch_status_t - notmuch_message_remove_all_properties (notmuch_message_t *message, - const char *key); - notmuch_message_properties_t * - notmuch_message_get_properties (notmuch_message_t *message, - const char *key, notmuch_bool_t exact); - notmuch_bool_t - notmuch_message_properties_valid (notmuch_message_properties_t - *properties); - void - notmuch_message_properties_move_to_next (notmuch_message_properties_t - *properties); - const char * - notmuch_message_properties_key (notmuch_message_properties_t *properties); - const char * - notmuch_message_properties_value (notmuch_message_properties_t - *properties); - void - notmuch_message_properties_destroy (notmuch_message_properties_t - *properties); - void - notmuch_message_destroy (notmuch_message_t *message); - - notmuch_bool_t - notmuch_tags_valid (notmuch_tags_t *tags); - const char * - notmuch_tags_get (notmuch_tags_t *tags); - void - notmuch_tags_move_to_next (notmuch_tags_t *tags); - void - notmuch_tags_destroy (notmuch_tags_t *tags); - - notmuch_bool_t - notmuch_filenames_valid (notmuch_filenames_t *filenames); - const char * - notmuch_filenames_get (notmuch_filenames_t *filenames); - void - notmuch_filenames_move_to_next (notmuch_filenames_t *filenames); - void - notmuch_filenames_destroy (notmuch_filenames_t *filenames); - notmuch_indexopts_t * - notmuch_database_get_default_indexopts (notmuch_database_t *db); - notmuch_status_t - notmuch_indexopts_set_decrypt_policy (notmuch_indexopts_t *indexopts, - notmuch_decryption_policy_t decrypt_policy); - notmuch_decryption_policy_t - notmuch_indexopts_get_decrypt_policy (const notmuch_indexopts_t *indexopts); - void - notmuch_indexopts_destroy (notmuch_indexopts_t *options); - - notmuch_status_t - notmuch_database_set_config (notmuch_database_t *db, const char *key, const char *value); - notmuch_status_t - notmuch_database_get_config (notmuch_database_t *db, const char *key, char **value); - notmuch_status_t - notmuch_database_get_config_list (notmuch_database_t *db, const char *prefix, notmuch_config_list_t **out); - notmuch_bool_t - notmuch_config_list_valid (notmuch_config_list_t *config_list); - const char * - notmuch_config_list_key (notmuch_config_list_t *config_list); - const char * - notmuch_config_list_value (notmuch_config_list_t *config_list); - void - notmuch_config_list_move_to_next (notmuch_config_list_t *config_list); - void - notmuch_config_list_destroy (notmuch_config_list_t *config_list); """ ) +ffibuilder.cdef(extract_functions()) -if __name__ == '__main__': +if __name__ == "__main__": ffibuilder.compile(verbose=True) diff --git a/bindings/python-cffi/pip-editable-build.sh b/bindings/python-cffi/pip-editable-build.sh new file mode 100755 index 00000000..22ea45f1 --- /dev/null +++ b/bindings/python-cffi/pip-editable-build.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# Shortcut to invoke `pip -e` with arguments that make it compile and +# link against the compiled notmuch in the repo's lib/ directory. +# This assumes it is being called with bindings/python-cff/ as cwd. + +set -x + +LIBDIR=../../lib + +pip install \ + --global-option=build_ext \ + --global-option=--include-dirs=$LIBDIR \ + --global-option=--library-dirs=$LIBDIR \ + --global-option=--rpath=$(pwd)/$LIBDIR \ + -e . diff --git a/lib/notmuch.h b/lib/notmuch.h index c66e78b1..92e052b9 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -41,7 +41,9 @@ NOTMUCH_BEGIN_DECLS +#ifndef PY_CFFI #include +#endif /* PY_CFFI */ #pragma GCC visibility push(default) @@ -62,6 +64,9 @@ NOTMUCH_BEGIN_DECLS #define LIBNOTMUCH_MICRO_VERSION 0 +#ifdef PY_CFFI +#define NOTMUCH_DEPRECATED(major, minor) +#else #if defined (__clang_major__) && __clang_major__ >= 3 \ || defined (__GNUC__) && __GNUC__ >= 5 \ || defined (__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 5 @@ -70,7 +75,7 @@ NOTMUCH_BEGIN_DECLS #else #define NOTMUCH_DEPRECATED(major, minor) __attribute__ ((deprecated)) #endif - +#endif /* PY_CFFI */ #endif /* __DOXYGEN__ */ @@ -637,11 +642,13 @@ notmuch_database_index_file (notmuch_database_t *database, * use notmuch_database_index_file instead. * */ +#ifndef PY_CFFI NOTMUCH_DEPRECATED (5, 1) notmuch_status_t notmuch_database_add_message (notmuch_database_t *database, const char *filename, notmuch_message_t **message); +#endif /** * Remove a message filename from the given notmuch database. If the @@ -935,9 +942,11 @@ notmuch_query_search_threads (notmuch_query_t *query, * use notmuch_query_search_threads instead. * */ +#ifndef PY_CFFI NOTMUCH_DEPRECATED (5, 0) notmuch_status_t notmuch_query_search_threads_st (notmuch_query_t *query, notmuch_threads_t **out); +#endif /** * Execute a query for messages, returning a notmuch_messages_t object @@ -990,11 +999,12 @@ notmuch_query_search_messages (notmuch_query_t *query, * notmuch_query_search_messages instead. * */ - +#ifndef PY_CFFI NOTMUCH_DEPRECATED (5, 0) notmuch_status_t notmuch_query_search_messages_st (notmuch_query_t *query, notmuch_messages_t **out); +#endif /** * Destroy a notmuch_query_t along with any associated resources. @@ -1087,9 +1097,11 @@ notmuch_query_count_messages (notmuch_query_t *query, unsigned int *count); * @deprecated Deprecated since libnotmuch 5.0 (notmuch 0.25). Please * use notmuch_query_count_messages instead. */ +#ifndef PY_CFFI NOTMUCH_DEPRECATED (5, 0) notmuch_status_t notmuch_query_count_messages_st (notmuch_query_t *query, unsigned int *count); +#endif /** * Return the number of threads matching a search. @@ -1122,9 +1134,11 @@ notmuch_query_count_threads (notmuch_query_t *query, unsigned *count); * @deprecated Deprecated as of libnotmuch 5.0 (notmuch 0.25). Please * use notmuch_query_count_threads_st instead. */ +#ifndef PY_CFFI NOTMUCH_DEPRECATED (5, 0) notmuch_status_t notmuch_query_count_threads_st (notmuch_query_t *query, unsigned *count); +#endif /** * Get the thread ID of 'thread'. @@ -1692,9 +1706,11 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message); * @returns FALSE in case of error * @deprecated libnotmuch 5.3 (notmuch 0.31) */ +#ifndef PY_CFFI NOTMUCH_DEPRECATED(5, 3) notmuch_bool_t notmuch_message_has_maildir_flag (notmuch_message_t *message, char flag); +#endif /** * check message for maildir flag -- 2.29.2