[alot] on Arch Linux

2011-12-14 Thread Philipp Überbacher

Hi there,
I'm a new notmuch/alot user, this is my first mail since I switched from
sup. Yes, switched. notmuch/alot works for me well enough now to be
usable.

I run Arch Linux. Here's some information for fellow Archers:
PKGBUILD for alot-git: https://aur.archlinux.org/packages.php?ID=54955
Should work just fine. If you want to help debug alot, change
_gitname=master to the name of the branch, build and install as usual.

You should currently avoid the alot PKGBUILD from AUR, it also points to
git and has some other mistakes. I'll see to it that it gets deleted and
maybe put a PKGBUILD with the release-version into its place.

Another little trap:
Arch doesn't supply a mailcap file, alot needs it for all those funky
html mails. As a solution until alot handles those mails better:
create ~/.mailcap
put the following line into it:
text/html; /usr/bin/lynx -dump '%s'; copiousoutput; description=HTML
Text; nametemplate=%s.html

Hope that helps,
thanks Patrick for writing alot, fixing bugs and helping with the
config.

Regards,
Philipp




ANNOUNCE: nottoomuch-addresses.pl version 1.4

2011-12-14 Thread Tomi Ollila

notmuch-addresses.sh -- email address substring matcher -- completion
helper version 1.4 is available.

This version uses 'notmuch search --sort=newest-first --output=files ...'
(instead of notmuch show ...) to retrieve message information from notmuch
... and now scans headers from mail files itself.

* This is now somewhat faster as the whole emails are not read.
* The sort order is better guaranteed.
* Current memory consumption of 'notmuch show --format=text' does not
  hit users.

Addresses file header format is same as in 1.3 so upgrading from that
version does not cause addresses file rebuild.

Location: http://www.iki.fi/too/nottoomuch/nottoomuch-addresses.sh

Sha1sum: 871f481a229a6e3295c02fa80270a7a318d226c

Web page: http://www.iki.fi/too/nottoomuch/nottoomuch-addresses/


Note to upgraders: this version may not find as many addreses as older
ones -- those also scanned From:, To: and Cc: in message bodies. 
Current version seldom leaks to the body of the message...
So, don't get alarmed if --update --rebuild finds less addresses.


Enjoy!
Tomi


[PATCH 2/5] lib: Add a MTIME value to every mail document

2011-12-14 Thread Austin Clements
A few minor comments below.

At a higher level, I'm curious what the tag synchronization protocol
you're building on top of this is.  I can't think of one that doesn't
have race conditions, but maybe I'm not thinking about it right.

Quoth Thomas Jost on Dec 13 at  6:11 pm:
> This is a time_t value, similar to the message date (TIMESTAMP). It is first 
> set
> when the message is added to the database, and is then updated every time a 
> tag
> is added or removed. It can thus be used for doing incremental dumps of the
> database or for synchronizing it between several computers.
> 
> This value can be read freely (with notmuch_message_get_mtime()) but for now 
> it
> can't be set to an arbitrary value: it can only be set to "now" when updated.
> There's no specific reason for this except that I don't really see a real use
> case for setting it to an arbitrary value.
> ---
>  lib/database.cc   |7 ++-
>  lib/message.cc|   32 
>  lib/notmuch-private.h |6 +-
>  lib/notmuch.h |4 
>  4 files changed, 47 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/database.cc b/lib/database.cc
> index 2025189..6dc6f73 100644
> --- a/lib/database.cc
> +++ b/lib/database.cc
> @@ -81,7 +81,7 @@ typedef struct {
>   *   STRING is the name of a file within that
>   *   directory for this mail message.
>   *
> - *A mail document also has four values:
> + *A mail document also has five values:
>   *
>   *   TIMESTAMP:  The time_t value corresponding to the message's
>   *   Date header.
> @@ -92,6 +92,9 @@ typedef struct {
>   *
>   *   SUBJECT:The value of the "Subject" header
>   *
> + *   MTIME:  The time_t value corresponding to the last time
> + *   a tag was added or removed on the message.
> + *
>   * In addition, terms from the content of the message are added with
>   * "from", "to", "attachment", and "subject" prefixes for use by the
>   * user in searching. Similarly, terms from the path of the mail
> @@ -1735,6 +1738,8 @@ notmuch_database_add_message (notmuch_database_t 
> *notmuch,
>   date = notmuch_message_file_get_header (message_file, "date");
>   _notmuch_message_set_header_values (message, date, from, subject);
>  
> +_notmuch_message_update_mtime (message);

Indentation.

> +
>   _notmuch_message_index_file (message, filename);
>   } else {
>   ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;
> diff --git a/lib/message.cc b/lib/message.cc
> index 0075425..0c98589 100644
> --- a/lib/message.cc
> +++ b/lib/message.cc
> @@ -830,6 +830,34 @@ _notmuch_message_set_header_values (notmuch_message_t 
> *message,
>  message->doc.add_value (NOTMUCH_VALUE_SUBJECT, subject);
>  }
>  
> +/* Get the message mtime, i.e. when it was added or the last time a tag was
> + * added/removed. */
> +time_t
> +notmuch_message_get_mtime (notmuch_message_t *message)
> +{
> +std::string value;
> +
> +try {
> + value = message->doc.get_value (NOTMUCH_VALUE_MTIME);
> +} catch (Xapian::Error ) {
> + INTERNAL_ERROR ("Failed to read mtime value from document.");
> + return 0;
> +}

For compatibility, this should handle the case when
NOTMUCH_VALUE_MTIME is missing, probably by just returning 0.  As it
is, value will be an empty string and sortable_unserialise is
undefined on strings that weren't produced by sortable_serialise.

> +
> +return Xapian::sortable_unserialise (value);
> +}
> +
> +/* Set the message mtime to "now". */
> +void
> +_notmuch_message_update_mtime (notmuch_message_t *message)
> +{
> +time_t time_value;
> +
> +time_value = time (NULL);
> +message->doc.add_value (NOTMUCH_VALUE_MTIME,
> +Xapian::sortable_serialise (time_value));

Indentation.

> +}
> +
>  /* Synchronize changes made to message->doc out into the database. */
>  void
>  _notmuch_message_sync (notmuch_message_t *message)
> @@ -994,6 +1022,8 @@ notmuch_message_add_tag (notmuch_message_t *message, 
> const char *tag)
>   private_status);
>  }
>  
> +_notmuch_message_update_mtime (message);
> +
>  if (! message->frozen)
>   _notmuch_message_sync (message);
>  
> @@ -1022,6 +1052,8 @@ notmuch_message_remove_tag (notmuch_message_t *message, 
> const char *tag)
>   private_status);
>  }
>  
> +_notmuch_message_update_mtime (message);
> +
>  if (! message->frozen)
>   _notmuch_message_sync (message);
>  
> diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
> index 60a932f..9859872 100644
> --- a/lib/notmuch-private.h
> +++ b/lib/notmuch-private.h
> @@ -95,7 +95,8 @@ typedef enum {
>  NOTMUCH_VALUE_TIMESTAMP = 0,
>  NOTMUCH_VALUE_MESSAGE_ID,
>  NOTMUCH_VALUE_FROM,
> -NOTMUCH_VALUE_SUBJECT
> +NOTMUCH_VALUE_SUBJECT,
> +NOTMUCH_VALUE_MTIME
>  } notmuch_value_t;
>  
>  /* Xapian (with flint 

[Alpha Patch 2/2] test: update dump-restore tests for 8 bit characters.

2011-12-14 Thread David Bremner
On Thu, 15 Dec 2011 00:36:38 +0400, Dmitry Kurochkin  wrote:
> 
> I did not do a proper review.  But I think the encoder and decoder
> should accept and return the same type, either char* or unsigned char*.
> The decision should be based on what type strings (that would be fed to
> the encoder and decoder) have in notmuch code.  I guess it is char*, so
> the encoder and decoder should take and return char*.  Internally we
> would cast char* to unsigned char*.

After staring at the draft C99 standard a bit, I'm inclined to agree. I
think char is the generic, which to my horror is really either unsigned
char or signed char is an implementation dependent way.

The info I was missing was in the description of 

,
| 3 For all functions in this subclause, each character shall be interpreted as 
if it had the type
|  unsigned char (and therefore every possible object representation is valid 
and has a
| different value).
`

I'll fix this in git, but I probably won't bother with another round of
patches yet.


[afew] announcing afew, an universal tagging solution with some fancy features

2011-12-14 Thread Patrick Totzke
Hi Justus,

I have just tried your script and have some questions/remarks about it:

* mkdir -p ~/.config/afew ~/.local/share/afew/categories
  As far as I can see, this is not needed if one doesn't use ClassifyingFilter,
  so its OK not to do this directly from the setup.py somehow.
  But it would be nice if a first run uf `afew --learn` would
  create these (or die gracefully instead of raising the 
afew.DBACL.BackendError).

* if you renamed the README & co to include the suffix ".md" github would nicely
  render them on the project page.

* I need some more info on how the config works: first, the order in which the
  sections are defined specifies the filter-pipeline yes?
  Secondly, what exactly is a "filter object" in the config?
  Specifically, what do these 3 lines do:
  https://github.com/teythoon/afew/blob/master/docs/tag_filters#L39

* this is surely a user error: I cannot use afew for initial tagging as 
expected:
  I installed as stated in the README,
  trained some of my existing tags and called `afew --update-reference` and 
`afew --update`.
  The test with `afew --classify -- ..` works nicely.
  Now I tagges all my mails with is:new, and called `afew --tag --new`.
  This returns immediately without output and all my messages are still tagged 
new.
  Also, -vv does not result in any output..
  ideas?

Looking forward to replacing my sort script with this.
Thanks,
/p





[PATCH v6 1/2] emacs: User-defined sections in notmuch-hello

2011-12-14 Thread Dmitry Kurochkin
On Wed, 14 Dec 2011 07:11:21 +0400, Dmitry Kurochkin  wrote:
> Hi Daniel.
> 
> I have finished reviewing this patch at last.  Sorry, it is a bit messy.
> Overall, I like the patch.  It is a very nice improvement.
> 
> I am sure I have missed some important points, but I guess this is the
> best I can do right now.  Perhaps I will find more comments for the next
> version of the patch :)
> 
> As we already discussed on IRC, there are some trailing whitespaces to
> cleanup.
> 
> Here is the review:
> 
> +(defvar notmuch-custom-section-options
> 
> s/notmuch-custom-section-options/notmuch-hello-custom-section-options/ for 
> consistency?
> 
> +(:filter-count (string :tag "Different filter message counts"))
> 
> It was not clear to me what this option is for from the docstring.
> Perhaps something like: "Count query filter, if different from :filter"?
> 
> +(:initially-hidden (const :tag "Hide this on startup?" t))
> 
> "This" refers to section, right?  If yes, let's state it explicitly:
> "Hide this section on startup".  Also, we should probably remove the
> question mark, or add it to other options for consistency.
> 
> Should the default be to show all sections?
> 
> +(:hide-if-empty (const :tag "Hide if empty" t)))
> 
> As I understand, this controls whether the whole sections is visible.
> It is not clear what "if empty" means.  Does it mean that all queries
> are empty?  Or all queries are empty and :show-empty-sections is
> false?  Consider changing to something like: "Hide this section if all
> queries are empty [and hidden]".
> 
> +  `(list :tag ""
> +  (const :tag "" notmuch-hello-insert-query-list)
> 
> Do we need to explicitly specify empty tags?  Aren't they empty by
> default?
> 
> +  :tag "Customized tag-list (see docstring for details)"
> +  :tag "Customized queries section (see docstring for details)"
> 
> Perhaps it would be more useful to add reference to
> `notmuch-hello-sections'?  I.e. "see `notmuch-hello-sections' for
> details.
> 
> Please s/Customized tag-list/Customized tag-list section/ everywhere for
> consistency (or remove section from "Customized queries section").
> 
> +Each entry of this list should be a function of no arguments that
> +should return if `notmuch-hello-target' is produced as part of its
> +output and nil otherwise.
> 
> Something is missing between "return if".  IMO it is really hard to
> understand what the function should actually do and what it should
> return.  Are this functions expected to add section content to current
> position?  As I understand, the return value indicates whether cursor
> should be positioned somewhere inside this section.  It is a minor
> detail, but it is described in the first (and complex sentence) as if
> it was the most important part.  Consider moving the return and "no
> arguments" to the 3rd paragraph which describes details about the
> functions.  I would also swap 2nd and 3rd paragraph.  Smth like:
> 
>   The list contains functions which are used to construct sections in
>   notmuch-hello buffer.  When notmuch-hello buffer is constructed,
>   these functions are run in the order they appear in this list.  Each
>   function produces a section simply by adding content to the current
>   buffer.  A section should not end with an empty line, because a
>   newline will be inserted after each section by `notmuch-hello'.
> 
>   Each function should take no arguments.  If the produced section
>   includes `notmuch-hello-target' (i.e. cursor should be positioned
>   inside this section), the function should return [something].
>   Otherwise, it should return nil.
> 
>   For convenience an element can also be a list of the form (FUNC ARG1
>   ARG2 .. ARGN) in which case FUNC will be applied to the rest of the
>   list.
> 
>   [ details about customized tag-list and queries sections ]
> 
> This is just a draft.  Feel free to use it or ignore it.
> 
> + For convenience an element can also be
> 
> Remove space the leading space and do `fill-paragraph'.
> 
> + (function :tag "Custom function"
> 
> Perhaps "Custom section" would be more accurate?
> 
> +  "Button at position of point before rebuilding the notmuch-buffer
> 
> Missing dot at the end.
> 
> s/Button/Button text/?
> 
> +This variable contains the string of the button, if any, the
> 
> s/the string/text/ or label?
> 
> +rebuilt. This is never actually set globally and defined as a
> 
> s/is never actually set/should never be set/?
> 
> +(defvar notmuch-hello-hidden-sections nil
> +  "List of query section titles whose contents are hidden")
> 
> Is this really for query sections only?
> 
> Does this duplicate :initially-hidden option from
> notmuch-custom-section-options?
> 
> How about adding a global alist variable notmuch-hello-state to store
> the state needed for section functions?  Currently, it would contain
> two values: :first-run and :target.  This would allow us to add more
> state variables in the future without polluting the global 

[Alpha Patch 2/2] test: update dump-restore tests for 8 bit characters.

2011-12-14 Thread David Bremner
From: David Bremner 

hex-escape: fix for handling of 8 bit chars

The low level problem was passing negative numbers to sprintf(s,"%x");
we fix this and clarify the api for hex_(decode|encode) by making
encode go from (unsigned char *) (i.e. 8bit) to (char *) and decode
vise-versa.
---
 test/dump-restore |2 --
 test/hex-escaping |1 -
 util/hex-escape.c |   26 +++---
 util/hex-escape.h |6 --
 4 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/test/dump-restore b/test/dump-restore
index eee1773..c5b2e86 100755
--- a/test/dump-restore
+++ b/test/dump-restore
@@ -114,7 +114,6 @@ notmuch dump --format=notmuch > BACKUP
 notmuch tag +"$tag1" +"$tag2" +"$tag3" -inbox -unread "*"

 test_begin_subtest 'format=notmuch, round trip with strange tags'
-   test_subtest_known_broken
notmuch dump --format=notmuch > EXPECTED.$test_count
notmuch dump --format=notmuch | notmuch restore --format=notmuch
notmuch dump --format=notmuch > OUTPUT.$test_count
@@ -122,7 +121,6 @@ test_expect_equal_file EXPECTED.$test_count 
OUTPUT.$test_count


 test_begin_subtest 'format=notmuch, checking encoded output'
-test_subtest_known_broken
 cp /dev/null EXPECTED.$test_count
 notmuch dump --format=notmuch -- from:cworth |\
 awk "{ print \$1 \" $enc1 $enc2 $enc3\" }" > EXPECTED.$test_count
diff --git a/test/hex-escaping b/test/hex-escaping
index 2053fb0..daa6446 100755
--- a/test/hex-escaping
+++ b/test/hex-escaping
@@ -19,7 +19,6 @@ $TEST_DIRECTORY/hex-xcode e  < EXPECTED.$test_count |\
 test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count

 test_begin_subtest "round trip 8bit chars"
-test_subtest_known_broken
 echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a' > EXPECTED.$test_count
 $TEST_DIRECTORY/hex-xcode d  < EXPECTED.$test_count |\
$TEST_DIRECTORY/hex-xcode e > OUTPUT.$test_count
diff --git a/util/hex-escape.c b/util/hex-escape.c
index dcf87cf..565ae99 100644
--- a/util/hex-escape.c
+++ b/util/hex-escape.c
@@ -28,23 +28,24 @@ static const size_t default_buf_size=1024;
 static const char* output_charset=
 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-_@=.:,";

-static const char escape_char='%';
+static const int escape_char = '%';

 static int
 is_output (char c) {
 return (strchr (output_charset, c) != NULL);
 }

+typedef unsigned char _octet;

 static int
-maybe_realloc(void *ctx, size_t needed, char **out, size_t *out_size)
+maybe_realloc(void *ctx, size_t needed, _octet **out, size_t *out_size)
 {
 if (*out_size < needed) {

if (*out == NULL)
*out = talloc_size(ctx,needed);
else
-   *out = talloc_realloc(ctx,*out,char,needed);
+   *out = talloc_realloc(ctx, *out, _octet, needed);

if (*out == NULL)
return 0;
@@ -56,24 +57,27 @@ maybe_realloc(void *ctx, size_t needed, char **out, size_t 
*out_size)


 hex_status_t
-hex_encode (void *ctx, const char *in, char **out, size_t *out_size)
+hex_encode (void *ctx, const _octet *in, char **out, size_t *out_size)
 {

-const char *p;
+const _octet *p;
 char *q;

-int escape_count=0;
+size_t escape_count = 0;
+size_t len = 0;
 size_t needed;

-for  (p = in; *p; p++)
+for  (p = in; *p; p++) {
escape_count += (! is_output (*p));
+   len++;
+}

-needed = strlen (in) + 2*escape_count + 1;
+needed = len + 2*escape_count + 1;

 if (*out == NULL)
*out_size=0;

-if (!maybe_realloc (ctx, needed, out, out_size))
+if (!maybe_realloc (ctx, needed, (_octet**)out, out_size))
return HEX_OUT_OF_MEMORY;

 q = *out;
@@ -94,12 +98,12 @@ hex_encode (void *ctx, const char *in, char **out, size_t 
*out_size)


 hex_status_t
-hex_decode (void *ctx, const char *in, char **out, size_t *out_size) {
+hex_decode (void *ctx, const char *in, _octet **out, size_t *out_size) {

 char buf[3];

 const char *p;
-char *q;
+_octet *q;

 size_t escape_count = 0;
 size_t needed = 0;
diff --git a/util/hex-escape.h b/util/hex-escape.h
index 98ecbe0..e04aff5 100644
--- a/util/hex-escape.h
+++ b/util/hex-escape.h
@@ -8,8 +8,10 @@ typedef enum hex_status {
 } hex_status_t;

 hex_status_t
-hex_encode (void *talloc_ctx, const char *in, char **out, size_t *out_size);
+hex_encode (void *talloc_ctx, const unsigned char *in, char **out,
+   size_t *out_size);

 hex_status_t
-hex_decode (void *talloc_ctx, const char *in, char **out, size_t *out_size);
+hex_decode (void *talloc_ctx, const char *in, unsigned char **out,
+   size_t *out_size);
 #endif
-- 
1.7.7.3



[Alpha Patch 1/2] test: add (currently broken) test 8 bit characters hex-escape and dump-restore

2011-12-14 Thread David Bremner
From: David Bremner 

The problem is a use of signed chars in places where unsigned
chars (i.e. 0-255) should be used.
---

Well, I did mention more tests were needed ;). I failed to test 8 bit
(>127) stuff and sure enough it was broken.  This sets up some tests
to demonstrate the problem and the next patch fixes it.

 test/dump-restore |9 +++--
 test/hex-escaping |7 +++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/test/dump-restore b/test/dump-restore
index 122de5c..eee1773 100755
--- a/test/dump-restore
+++ b/test/dump-restore
@@ -106,11 +106,15 @@ enc1=$($TEST_DIRECTORY/hex-xcode e "$tag1")
 tag2=$(printf 'this\n tag\t has\n spaces')
 enc2=$($TEST_DIRECTORY/hex-xcode e "$tag2")

+enc3='%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a'
+tag3=$($TEST_DIRECTORY/hex-xcode d $enc3)
+
 notmuch dump --format=notmuch > BACKUP

-notmuch tag +"$tag1" +"$tag2" -inbox -unread "*"
+notmuch tag +"$tag1" +"$tag2" +"$tag3" -inbox -unread "*"

 test_begin_subtest 'format=notmuch, round trip with strange tags'
+   test_subtest_known_broken
notmuch dump --format=notmuch > EXPECTED.$test_count
notmuch dump --format=notmuch | notmuch restore --format=notmuch
notmuch dump --format=notmuch > OUTPUT.$test_count
@@ -118,9 +122,10 @@ test_expect_equal_file EXPECTED.$test_count 
OUTPUT.$test_count


 test_begin_subtest 'format=notmuch, checking encoded output'
+test_subtest_known_broken
 cp /dev/null EXPECTED.$test_count
 notmuch dump --format=notmuch -- from:cworth |\
-awk "{ print \$1 \" $enc1 $enc2\" }" > EXPECTED.$test_count
+awk "{ print \$1 \" $enc1 $enc2 $enc3\" }" > EXPECTED.$test_count

 notmuch dump --format=notmuch -- from:cworth  > OUTPUT.$test_count
 test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
diff --git a/test/hex-escaping b/test/hex-escaping
index d0a993e..2053fb0 100755
--- a/test/hex-escaping
+++ b/test/hex-escaping
@@ -17,4 +17,11 @@ printf 'this\n tag\t has\n spaces\n' > EXPECTED.$test_count
 $TEST_DIRECTORY/hex-xcode e  < EXPECTED.$test_count |\
$TEST_DIRECTORY/hex-xcode d > OUTPUT.$test_count
 test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest "round trip 8bit chars"
+test_subtest_known_broken
+echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a' > EXPECTED.$test_count
+$TEST_DIRECTORY/hex-xcode d  < EXPECTED.$test_count |\
+   $TEST_DIRECTORY/hex-xcode e > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
 test_done
-- 
1.7.7.3



[PATCH 2/5] lib: Add a MTIME value to every mail document

2011-12-14 Thread Mark Anderson
On Tue, 13 Dec 2011 11:11:42 -0600, Thomas Jost  
wrote:
> This is a time_t value, similar to the message date (TIMESTAMP). It is first 
> set
> when the message is added to the database, and is then updated every time a 
> tag
> is added or removed. It can thus be used for doing incremental dumps of the
> database or for synchronizing it between several computers.
> 
> This value can be read freely (with notmuch_message_get_mtime()) but for now 
> it
> can't be set to an arbitrary value: it can only be set to "now" when updated.
> There's no specific reason for this except that I don't really see a real use
> case for setting it to an arbitrary value.

I think it would be easier to write some testcases if the last modified
time could be touched directly.  Perhaps they aren't in the set of "must
have", but it's what comes to mind.

-Mark

> ---
>  lib/database.cc   |7 ++-
>  lib/message.cc|   32 
>  lib/notmuch-private.h |6 +-
>  lib/notmuch.h |4 
>  4 files changed, 47 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/database.cc b/lib/database.cc
> index 2025189..6dc6f73 100644
> --- a/lib/database.cc
> +++ b/lib/database.cc
> @@ -81,7 +81,7 @@ typedef struct {
>   *   STRING is the name of a file within that
>   *   directory for this mail message.
>   *
> - *A mail document also has four values:
> + *A mail document also has five values:
>   *
>   *   TIMESTAMP:  The time_t value corresponding to the message's
>   *   Date header.
> @@ -92,6 +92,9 @@ typedef struct {
>   *
>   *   SUBJECT:The value of the "Subject" header
>   *
> + *   MTIME:  The time_t value corresponding to the last time
> + *   a tag was added or removed on the message.
> + *
>   * In addition, terms from the content of the message are added with
>   * "from", "to", "attachment", and "subject" prefixes for use by the
>   * user in searching. Similarly, terms from the path of the mail
> @@ -1735,6 +1738,8 @@ notmuch_database_add_message (notmuch_database_t 
> *notmuch,
>   date = notmuch_message_file_get_header (message_file, "date");
>   _notmuch_message_set_header_values (message, date, from, subject);
>  
> +_notmuch_message_update_mtime (message);
> +
>   _notmuch_message_index_file (message, filename);
>   } else {
>   ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;
> diff --git a/lib/message.cc b/lib/message.cc
> index 0075425..0c98589 100644
> --- a/lib/message.cc
> +++ b/lib/message.cc
> @@ -830,6 +830,34 @@ _notmuch_message_set_header_values (notmuch_message_t 
> *message,
>  message->doc.add_value (NOTMUCH_VALUE_SUBJECT, subject);
>  }
>  
> +/* Get the message mtime, i.e. when it was added or the last time a tag was
> + * added/removed. */
> +time_t
> +notmuch_message_get_mtime (notmuch_message_t *message)
> +{
> +std::string value;
> +
> +try {
> + value = message->doc.get_value (NOTMUCH_VALUE_MTIME);
> +} catch (Xapian::Error ) {
> + INTERNAL_ERROR ("Failed to read mtime value from document.");
> + return 0;
> +}
> +
> +return Xapian::sortable_unserialise (value);
> +}
> +
> +/* Set the message mtime to "now". */
> +void
> +_notmuch_message_update_mtime (notmuch_message_t *message)
> +{
> +time_t time_value;
> +
> +time_value = time (NULL);
> +message->doc.add_value (NOTMUCH_VALUE_MTIME,
> +Xapian::sortable_serialise (time_value));
> +}
> +
>  /* Synchronize changes made to message->doc out into the database. */
>  void
>  _notmuch_message_sync (notmuch_message_t *message)
> @@ -994,6 +1022,8 @@ notmuch_message_add_tag (notmuch_message_t *message, 
> const char *tag)
>   private_status);
>  }
>  
> +_notmuch_message_update_mtime (message);
> +
>  if (! message->frozen)
>   _notmuch_message_sync (message);
>  
> @@ -1022,6 +1052,8 @@ notmuch_message_remove_tag (notmuch_message_t *message, 
> const char *tag)
>   private_status);
>  }
>  
> +_notmuch_message_update_mtime (message);
> +
>  if (! message->frozen)
>   _notmuch_message_sync (message);
>  
> diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
> index 60a932f..9859872 100644
> --- a/lib/notmuch-private.h
> +++ b/lib/notmuch-private.h
> @@ -95,7 +95,8 @@ typedef enum {
>  NOTMUCH_VALUE_TIMESTAMP = 0,
>  NOTMUCH_VALUE_MESSAGE_ID,
>  NOTMUCH_VALUE_FROM,
> -NOTMUCH_VALUE_SUBJECT
> +NOTMUCH_VALUE_SUBJECT,
> +NOTMUCH_VALUE_MTIME
>  } notmuch_value_t;
>  
>  /* Xapian (with flint backend) complains if we provide a term longer
> @@ -276,6 +277,9 @@ _notmuch_message_set_header_values (notmuch_message_t 
> *message,
>   const char *from,
>   const char *subject);
>  void
> +_notmuch_message_update_mtime (notmuch_message_t 

[PATCH 6/7] py3k: Add and use a mixin class that implements __str__

2011-12-14 Thread Tomi Ollila
On Wed, 14 Dec 2011 11:58:24 +0100, Justus Winter <4winter at 
informatik.uni-hamburg.de> wrote:
> ---
[ ... snip ... ]

>  
> -class Filenames(object):
> +class Filenames(Python3StringMixIn):
>  """Represents a list of filenames as returned by notmuch
>  
>  This object contains the Filenames iterator. The main function is
> @@ -98,9 +98,6 @@ class Filenames(object):
>  
>  self._files = None
>  
> -def __str__(self):
> -return unicode(self).encode('utf-8')
> -
>  def __unicode__(self):
>  """Represent Filenames() as newline-separated list of full paths
>  
> diff --git a/bindings/python/notmuch/globals.py 
> b/bindings/python/notmuch/globals.py
> index c52790c..2111b86 100644
> --- a/bindings/python/notmuch/globals.py
> +++ b/bindings/python/notmuch/globals.py
> @@ -28,6 +28,16 @@ except:
>  raise ImportError("Could not find shared 'notmuch' library.")
>  
>  
> +if sys.version_info[0] == 2:
> +class Python3StringMixIn(object):
> +def __str__(self):
> +return unicode(self).encode('utf-8')
> +else:
> +class Python3StringMixIn(object):
> +def __str__(self):
> +return self.__unicode__()
> +
> +

[ ... snip ... ]

> -class Threads(object):
> +class Threads(Python3StringMixIn):
>  """Represents a list of notmuch threads
>  
>  This object provides an iterator over a list of notmuch threads
> @@ -393,7 +393,7 @@ class Thread(object):
>  return Tags(tags_p, self)
>  
>  def __str__(self):
> -return unicode(self).encode('utf-8')
> +return self.__unicode__().encode('utf-8')
>  
>  def __unicode__(self):
>  frm = "thread:%s %12s [%d/%d] %s; %s (%s)"

Is this class special case ? in all other classes
the __str__() function has been removed (using inherited
function) ?

> -- 
> 1.7.7.3

Otherwise LGTM -- pretty simple and effective (all 7 patches).

Tomi



[PATCH 3/7] py3k: All strings are unicode strings in py3k

2011-12-14 Thread Tomi Ollila
On Wed, 14 Dec 2011 11:58:21 +0100, Justus Winter <4winter at 
informatik.uni-hamburg.de> wrote:
> ---
>  bindings/python/notmuch/globals.py |4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/bindings/python/notmuch/globals.py 
> b/bindings/python/notmuch/globals.py
> index 54a49b2..99e6a10 100644
> --- a/bindings/python/notmuch/globals.py
> +++ b/bindings/python/notmuch/globals.py
> @@ -51,7 +51,7 @@ class Status(Enum):
>  """Get a (unicode) string representation of a notmuch_status_t 
> value."""
>  # define strings for custom error messages
>  if status == STATUS.NOT_INITIALIZED:
> -return u"Operation on uninitialized object impossible."
> +return "Operation on uninitialized object impossible."
>  return unicode(Status._status2str(status))
>  
>  STATUS = Status(['SUCCESS',
> @@ -142,7 +142,7 @@ class NotmuchError(Exception):
>  elif self.status is not None:
>  return STATUS.status2str(self.status)
>  else:
> -return u'Unknown error'
> +return 'Unknown error'

Is this u -prefix unnecessary in python 2 too ? Grepping
'u"' and "u'" in **/*.py in puthon bindings source resulted
some more u-prefixed strings in docs/source/conf.py. Should
these be changed in some future patch ?

>  # List of Subclassed exceptions that correspond to STATUS values and are
> -- 
> 1.7.7.3

Tomi


[PATCH 6/7] py3k: Add and use a mixin class that implements __str__

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/filename.py |7 ++-
 bindings/python/notmuch/globals.py  |   15 +++
 bindings/python/notmuch/message.py  |8 +++-
 bindings/python/notmuch/tag.py  |7 ++-
 bindings/python/notmuch/thread.py   |7 ++-
 5 files changed, 20 insertions(+), 24 deletions(-)

diff --git a/bindings/python/notmuch/filename.py 
b/bindings/python/notmuch/filename.py
index a7cd7e6..969931a 100644
--- a/bindings/python/notmuch/filename.py
+++ b/bindings/python/notmuch/filename.py
@@ -18,10 +18,10 @@ Copyright 2010 Sebastian Spaeth '
 """
 from ctypes import c_char_p
 from notmuch.globals import (nmlib, STATUS, NotmuchError,
-NotmuchFilenamesP, NotmuchMessageP)
+NotmuchFilenamesP, NotmuchMessageP, _str, Python3StringMixIn)


-class Filenames(object):
+class Filenames(Python3StringMixIn):
 """Represents a list of filenames as returned by notmuch

 This object contains the Filenames iterator. The main function is
@@ -98,9 +98,6 @@ class Filenames(object):

 self._files = None

-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 """Represent Filenames() as newline-separated list of full paths

diff --git a/bindings/python/notmuch/globals.py 
b/bindings/python/notmuch/globals.py
index c52790c..2111b86 100644
--- a/bindings/python/notmuch/globals.py
+++ b/bindings/python/notmuch/globals.py
@@ -28,6 +28,16 @@ except:
 raise ImportError("Could not find shared 'notmuch' library.")


+if sys.version_info[0] == 2:
+class Python3StringMixIn(object):
+def __str__(self):
+return unicode(self).encode('utf-8')
+else:
+class Python3StringMixIn(object):
+def __str__(self):
+return self.__unicode__()
+
+
 class Enum(object):
 """Provides ENUMS as "code=Enum(['a','b','c'])" where code.a=0 etc..."""
 def __init__(self, names):
@@ -90,7 +100,7 @@ argument to receive a human readable string"""
 STATUS.__name__ = 'STATUS'


-class NotmuchError(Exception):
+class NotmuchError(Exception, Python3StringMixIn):
 """Is initiated with a (notmuch.STATUS[, message=None]). It will not
 return an instance of the class NotmuchError, but a derived instance
 of a more specific Error Message, e.g. OutOfMemoryError. Each status
@@ -134,9 +144,6 @@ class NotmuchError(Exception):
 self.status = status
 self.message = message

-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 if self.message is not None:
 return self.message
diff --git a/bindings/python/notmuch/message.py 
b/bindings/python/notmuch/message.py
index bf0c4da..955382d 100644
--- a/bindings/python/notmuch/message.py
+++ b/bindings/python/notmuch/message.py
@@ -21,7 +21,8 @@ Copyright 2010 Sebastian Spaeth '

 from ctypes import c_char_p, c_long, c_uint, c_int
 from datetime import date
-from notmuch.globals import (nmlib, STATUS, NotmuchError, Enum, _str,
+from notmuch.globals import (
+nmlib, STATUS, NotmuchError, Enum, _str, Python3StringMixIn,
 NotmuchTagsP, NotmuchMessagesP, NotmuchMessageP, NotmuchFilenamesP)
 from notmuch.tag import Tags
 from notmuch.filename import Filenames
@@ -239,7 +240,7 @@ class Messages(object):
 sys.stdout.write(set_end)


-class Message(object):
+class Message(Python3StringMixIn):
 """Represents a single Email message

 Technically, this wraps the underlying *notmuch_message_t*
@@ -796,9 +797,6 @@ class Message(object):
 """Represent a Message() object by str()"""
 return self.__str__()

-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 format = "%s (%s) (%s)"
 return format % (self.get_header('from'),
diff --git a/bindings/python/notmuch/tag.py b/bindings/python/notmuch/tag.py
index d42ba77..ceb7244 100644
--- a/bindings/python/notmuch/tag.py
+++ b/bindings/python/notmuch/tag.py
@@ -17,10 +17,10 @@ along with notmuch.  If not, see 
.
 Copyright 2010 Sebastian Spaeth '
 """
 from ctypes import c_char_p
-from notmuch.globals import nmlib, STATUS, NotmuchError, NotmuchTagsP
+from notmuch.globals import nmlib, STATUS, NotmuchError, NotmuchTagsP, _str, 
Python3StringMixIn


-class Tags(object):
+class Tags(Python3StringMixIn):
 """Represents a list of notmuch tags

 This object provides an iterator over a list of notmuch tags (which
@@ -111,9 +111,6 @@ class Tags(object):
 left."""
 return self._valid(self._tags) > 0

-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 """string representation of :class:`Tags`: a space separated list of 
tags

diff --git a/bindings/python/notmuch/thread.py 
b/bindings/python/notmuch/thread.py
index 39285d6..7393097 100644
--- a/bindings/python/notmuch/thread.py
+++ b/bindings/python/notmuch/thread.py
@@ -20,13 +20,13 @@ 

[PATCH 3/7] py3k: All strings are unicode strings in py3k

2011-12-14 Thread Justus Winter
Hi Tomi :)

Quoting Tomi Ollila (2011-12-14 13:17:41)
>On Wed, 14 Dec 2011 11:58:21 +0100, Justus Winter <4winter at 
>informatik.uni-hamburg.de> wrote:
>> ---
>>  bindings/python/notmuch/globals.py |4 ++--
>>  1 files changed, 2 insertions(+), 2 deletions(-)
>> 
>> diff --git a/bindings/python/notmuch/globals.py 
>> b/bindings/python/notmuch/globals.py
>> index 54a49b2..99e6a10 100644
>> --- a/bindings/python/notmuch/globals.py
>> +++ b/bindings/python/notmuch/globals.py
>> @@ -51,7 +51,7 @@ class Status(Enum):
>>  """Get a (unicode) string representation of a notmuch_status_t 
>> value."""
>>  # define strings for custom error messages
>>  if status == STATUS.NOT_INITIALIZED:
>> -return u"Operation on uninitialized object impossible."
>> +return "Operation on uninitialized object impossible."
>>  return unicode(Status._status2str(status))
>>  
>>  STATUS = Status(['SUCCESS',
>> @@ -142,7 +142,7 @@ class NotmuchError(Exception):
>>  elif self.status is not None:
>>  return STATUS.status2str(self.status)
>>  else:
>> -return u'Unknown error'
>> +return 'Unknown error'
>
>Is this u -prefix unnecessary in python 2 too ? Grepping
>'u"' and "u'" in **/*.py in puthon bindings source resulted
>some more u-prefixed strings in docs/source/conf.py. Should
>these be changed in some future patch ?

Well, since the string literal contains no non-ascii characters it is
perfectly safe to just use a (python2.x) string literal and it will be
automatically coerced to unicode if it is used in a unicode context.

OTOH it is possible to use

from __future__ import unicode_literals

to turn all string literals to unicode literals in python 2.x.

Justus
-- next part --
A non-text attachment was scrubbed...
Name: .signature
Type: application/octet-stream
Size: 17 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20111214/30164683/attachment-0001.obj>


[afew] announcing afew,

2011-12-14 Thread Justus Winter
Quoting Kazuo Teramoto (2011-12-14 12:24:14)
>an universal tagging solution with some fancy features
>From: Kazuo Teramoto 
>In-Reply-To: 
>On 2011-12-14T08:42:36, Justus Winter wrote:
>>I'd like to introduce my initial tagging approach, afew tags:
>>
>>https://github.com/teythoon/afew
>>
>
>Very good! Thanks for it. I'm using it as my only filtering/tagging
>solutions and works great.
>
>I created a Arch Linux PKGBUILD, it can be find at [aur]

Cool :)

> (about it,
>Justus how you define the afew license? I put a 'unknown' in the license
>as I can give it a names like BSD or GPL or WTFPL).

afew is licensed under a modern BSD license (I used the openbsd
license). It is included in every source file.

>>* works with both python2.7 and python3.2
>
>Python 3 support need the patch set you send to the list, correct?

Yes.

Cheers,
Justus
-- next part --
A non-text attachment was scrubbed...
Name: .signature
Type: application/octet-stream
Size: 17 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20111214/b2a08933/attachment.obj>


[afew] announcing afew, an universal tagging solution with some fancy features

2011-12-14 Thread Jani Nikula
On Wed, 14 Dec 2011 11:42:36 +0100, Justus Winter <4winter at 
informatik.uni-hamburg.de> wrote:
> https://github.com/teythoon/afew
> 
> It has some nifty features, citing the README:

"""
Basic tagging stuff requires no configuration, just run

$ afew --tag --new

To do this automatically you can add the following hook into your
~/.offlineimaprc:

postsynchook = ionice -c 3 chrt --idle 0 /bin/sh -c "notmuch new && afew
--tag --new"
"""

FYI, "notmuch new" now supports hooks you can use for this. Currently
only in the git repo, though.

BR,
Jani.


[PATCH 7/7] python: add missing conversions from and to utf-8

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/database.py |6 +++---
 bindings/python/notmuch/filename.py |2 +-
 bindings/python/notmuch/message.py  |8 
 bindings/python/notmuch/thread.py   |2 +-
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/bindings/python/notmuch/database.py 
b/bindings/python/notmuch/database.py
index 3f6e04d..2eae69e 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -430,7 +430,7 @@ class Database(object):
removed.
 """
 self._assert_db_is_initialized()
-return self._remove_message(self._db, filename)
+return self._remove_message(self._db, _str(filename))

 def find_message(self, msgid):
 """Returns a :class:`Message` as identified by its message ID
@@ -933,9 +933,9 @@ class Filenames(object):
 self._files_p = None
 raise StopIteration

-file = Filenames._get(self._files_p)
+file_ = Filenames._get(self._files_p)
 self._move_to_next(self._files_p)
-return file
+return file_.decode('utf-8', errors='ignore')
 next = __next__ # python2.x iterator protocol compatibility

 def __len__(self):
diff --git a/bindings/python/notmuch/filename.py 
b/bindings/python/notmuch/filename.py
index 969931a..0c2e0d5 100644
--- a/bindings/python/notmuch/filename.py
+++ b/bindings/python/notmuch/filename.py
@@ -93,7 +93,7 @@ class Filenames(Python3StringMixIn):
 raise NotmuchError(STATUS.NOT_INITIALIZED)

 while self._valid(self._files):
-yield Filenames._get(self._files)
+yield Filenames._get(self._files).decode('utf-8', errors='ignore')
 self._move_to_next(self._files)

 self._files = None
diff --git a/bindings/python/notmuch/message.py 
b/bindings/python/notmuch/message.py
index 955382d..245e814 100644
--- a/bindings/python/notmuch/message.py
+++ b/bindings/python/notmuch/message.py
@@ -338,7 +338,7 @@ class Message(Python3StringMixIn):
 """
 if self._msg is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
-return Message._get_message_id(self._msg)
+return Message._get_message_id(self._msg).decode('utf-8', 
errors='ignore')

 def get_thread_id(self):
 """Returns the thread ID
@@ -356,7 +356,7 @@ class Message(Python3StringMixIn):
 if self._msg is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)

-return Message._get_thread_id(self._msg)
+return Message._get_thread_id(self._msg).decode('utf-8', 
errors='ignore')

 def get_replies(self):
 """Gets all direct replies to this message as :class:`Messages`
@@ -426,7 +426,7 @@ class Message(Python3StringMixIn):
 raise NotmuchError(STATUS.NOT_INITIALIZED)

 #Returns NULL if any error occurs.
-header = Message._get_header(self._msg, header)
+header = Message._get_header(self._msg, _str(header))
 if header == None:
 raise NotmuchError(STATUS.NULL_POINTER)
 return header.decode('UTF-8', errors='ignore')
@@ -440,7 +440,7 @@ class Message(Python3StringMixIn):
 """
 if self._msg is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
-return Message._get_filename(self._msg)
+return Message._get_filename(self._msg).decode('utf-8', 
errors='ignore')

 def get_filenames(self):
 """Get all filenames for the email corresponding to 'message'
diff --git a/bindings/python/notmuch/thread.py 
b/bindings/python/notmuch/thread.py
index 3912957..2ed7db0 100644
--- a/bindings/python/notmuch/thread.py
+++ b/bindings/python/notmuch/thread.py
@@ -246,7 +246,7 @@ class Thread(object):
 """
 if self._thread is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
-return Thread._get_thread_id(self._thread)
+return Thread._get_thread_id(self._thread).decode('utf-8', 
errors='ignore')

 _get_total_messages = nmlib.notmuch_thread_get_total_messages
 _get_total_messages.argtypes = [NotmuchThreadP]
-- 
1.7.7.3



[PATCH 6/7] py3k: Add and use a mixin class that implements __str__

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/filename.py |7 ++-
 bindings/python/notmuch/globals.py  |   15 +++
 bindings/python/notmuch/message.py  |8 +++-
 bindings/python/notmuch/tag.py  |7 ++-
 bindings/python/notmuch/thread.py   |6 +++---
 5 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/bindings/python/notmuch/filename.py 
b/bindings/python/notmuch/filename.py
index a7cd7e6..969931a 100644
--- a/bindings/python/notmuch/filename.py
+++ b/bindings/python/notmuch/filename.py
@@ -18,10 +18,10 @@ Copyright 2010 Sebastian Spaeth '
 """
 from ctypes import c_char_p
 from notmuch.globals import (nmlib, STATUS, NotmuchError,
-NotmuchFilenamesP, NotmuchMessageP)
+NotmuchFilenamesP, NotmuchMessageP, _str, Python3StringMixIn)


-class Filenames(object):
+class Filenames(Python3StringMixIn):
 """Represents a list of filenames as returned by notmuch

 This object contains the Filenames iterator. The main function is
@@ -98,9 +98,6 @@ class Filenames(object):

 self._files = None

-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 """Represent Filenames() as newline-separated list of full paths

diff --git a/bindings/python/notmuch/globals.py 
b/bindings/python/notmuch/globals.py
index c52790c..2111b86 100644
--- a/bindings/python/notmuch/globals.py
+++ b/bindings/python/notmuch/globals.py
@@ -28,6 +28,16 @@ except:
 raise ImportError("Could not find shared 'notmuch' library.")


+if sys.version_info[0] == 2:
+class Python3StringMixIn(object):
+def __str__(self):
+return unicode(self).encode('utf-8')
+else:
+class Python3StringMixIn(object):
+def __str__(self):
+return self.__unicode__()
+
+
 class Enum(object):
 """Provides ENUMS as "code=Enum(['a','b','c'])" where code.a=0 etc..."""
 def __init__(self, names):
@@ -90,7 +100,7 @@ argument to receive a human readable string"""
 STATUS.__name__ = 'STATUS'


-class NotmuchError(Exception):
+class NotmuchError(Exception, Python3StringMixIn):
 """Is initiated with a (notmuch.STATUS[, message=None]). It will not
 return an instance of the class NotmuchError, but a derived instance
 of a more specific Error Message, e.g. OutOfMemoryError. Each status
@@ -134,9 +144,6 @@ class NotmuchError(Exception):
 self.status = status
 self.message = message

-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 if self.message is not None:
 return self.message
diff --git a/bindings/python/notmuch/message.py 
b/bindings/python/notmuch/message.py
index bf0c4da..955382d 100644
--- a/bindings/python/notmuch/message.py
+++ b/bindings/python/notmuch/message.py
@@ -21,7 +21,8 @@ Copyright 2010 Sebastian Spaeth '

 from ctypes import c_char_p, c_long, c_uint, c_int
 from datetime import date
-from notmuch.globals import (nmlib, STATUS, NotmuchError, Enum, _str,
+from notmuch.globals import (
+nmlib, STATUS, NotmuchError, Enum, _str, Python3StringMixIn,
 NotmuchTagsP, NotmuchMessagesP, NotmuchMessageP, NotmuchFilenamesP)
 from notmuch.tag import Tags
 from notmuch.filename import Filenames
@@ -239,7 +240,7 @@ class Messages(object):
 sys.stdout.write(set_end)


-class Message(object):
+class Message(Python3StringMixIn):
 """Represents a single Email message

 Technically, this wraps the underlying *notmuch_message_t*
@@ -796,9 +797,6 @@ class Message(object):
 """Represent a Message() object by str()"""
 return self.__str__()

-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 format = "%s (%s) (%s)"
 return format % (self.get_header('from'),
diff --git a/bindings/python/notmuch/tag.py b/bindings/python/notmuch/tag.py
index d42ba77..ceb7244 100644
--- a/bindings/python/notmuch/tag.py
+++ b/bindings/python/notmuch/tag.py
@@ -17,10 +17,10 @@ along with notmuch.  If not, see 
.
 Copyright 2010 Sebastian Spaeth '
 """
 from ctypes import c_char_p
-from notmuch.globals import nmlib, STATUS, NotmuchError, NotmuchTagsP
+from notmuch.globals import nmlib, STATUS, NotmuchError, NotmuchTagsP, _str, 
Python3StringMixIn


-class Tags(object):
+class Tags(Python3StringMixIn):
 """Represents a list of notmuch tags

 This object provides an iterator over a list of notmuch tags (which
@@ -111,9 +111,6 @@ class Tags(object):
 left."""
 return self._valid(self._tags) > 0

-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 """string representation of :class:`Tags`: a space separated list of 
tags

diff --git a/bindings/python/notmuch/thread.py 
b/bindings/python/notmuch/thread.py
index 39285d6..3912957 100644
--- a/bindings/python/notmuch/thread.py
+++ b/bindings/python/notmuch/thread.py
@@ -20,13 +20,13 @@ 

[PATCH 5/7] py3k: the basestring and unicode types are removed in python 3

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/globals.py |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch/globals.py 
b/bindings/python/notmuch/globals.py
index 99e6a10..c52790c 100644
--- a/bindings/python/notmuch/globals.py
+++ b/bindings/python/notmuch/globals.py
@@ -17,6 +17,7 @@ along with notmuch.  If not, see 
.
 Copyright 2010 Sebastian Spaeth '
 """

+import sys
 from ctypes import CDLL, c_char_p, c_int, Structure, POINTER

 #-
@@ -200,9 +201,9 @@ def _str(value):

 C++ code expects strings to be well formatted and
 unicode strings to have no null bytes."""
-if not isinstance(value, basestring):
+if not isinstance(value, basestring if sys.version_info[0] == 2 else str):
 raise TypeError("Expected str or unicode, got %s" % str(type(value)))
-if isinstance(value, unicode):
+if sys.version_info[0] == 3 or isinstance(value, unicode):
 return value.encode('UTF-8')
 return value

-- 
1.7.7.3



[PATCH 4/7] py3k: Rename .next() to __next__(), add python2.x compatibility alias

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/database.py |3 ++-
 bindings/python/notmuch/message.py  |3 ++-
 bindings/python/notmuch/tag.py  |3 ++-
 bindings/python/notmuch/thread.py   |3 ++-
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/bindings/python/notmuch/database.py 
b/bindings/python/notmuch/database.py
index 9318368..3f6e04d 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -925,7 +925,7 @@ class Filenames(object):
 _move_to_next.argtypes = [NotmuchFilenamesP]
 _move_to_next.restype = None

-def next(self):
+def __next__(self):
 if self._files_p is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)

@@ -936,6 +936,7 @@ class Filenames(object):
 file = Filenames._get(self._files_p)
 self._move_to_next(self._files_p)
 return file
+next = __next__ # python2.x iterator protocol compatibility

 def __len__(self):
 """len(:class:`Filenames`) returns the number of contained files
diff --git a/bindings/python/notmuch/message.py 
b/bindings/python/notmuch/message.py
index ce8e718..bf0c4da 100644
--- a/bindings/python/notmuch/message.py
+++ b/bindings/python/notmuch/message.py
@@ -158,7 +158,7 @@ class Messages(object):
 _move_to_next.argtypes = [NotmuchMessagesP]
 _move_to_next.restype = None

-def next(self):
+def __next__(self):
 if self._msgs is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)

@@ -169,6 +169,7 @@ class Messages(object):
 msg = Message(Messages._get(self._msgs), self)
 self._move_to_next(self._msgs)
 return msg
+next = __next__ # python2.x iterator protocol compatibility

 def __nonzero__(self):
 """
diff --git a/bindings/python/notmuch/tag.py b/bindings/python/notmuch/tag.py
index 2fb7d32..d42ba77 100644
--- a/bindings/python/notmuch/tag.py
+++ b/bindings/python/notmuch/tag.py
@@ -89,7 +89,7 @@ class Tags(object):
 _move_to_next.argtypes = [NotmuchTagsP]
 _move_to_next.restype = None

-def next(self):
+def __next__(self):
 if self._tags is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
 if not self._valid(self._tags):
@@ -98,6 +98,7 @@ class Tags(object):
 tag = Tags._get(self._tags).decode('UTF-8')
 self._move_to_next(self._tags)
 return tag
+next = __next__ # python2.x iterator protocol compatibility

 def __nonzero__(self):
 """Implement bool(Tags) check that can be repeatedly used
diff --git a/bindings/python/notmuch/thread.py 
b/bindings/python/notmuch/thread.py
index 5058846..39285d6 100644
--- a/bindings/python/notmuch/thread.py
+++ b/bindings/python/notmuch/thread.py
@@ -116,7 +116,7 @@ class Threads(object):
 _move_to_next.argtypes = [NotmuchThreadsP]
 _move_to_next.restype = None

-def next(self):
+def __next__(self):
 if self._threads is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)

@@ -127,6 +127,7 @@ class Threads(object):
 thread = Thread(Threads._get(self._threads), self)
 self._move_to_next(self._threads)
 return thread
+next = __next__ # python2.x iterator protocol compatibility

 def __len__(self):
 """len(:class:`Threads`) returns the number of contained Threads
-- 
1.7.7.3



[PATCH 3/7] py3k: All strings are unicode strings in py3k

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/globals.py |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch/globals.py 
b/bindings/python/notmuch/globals.py
index 54a49b2..99e6a10 100644
--- a/bindings/python/notmuch/globals.py
+++ b/bindings/python/notmuch/globals.py
@@ -51,7 +51,7 @@ class Status(Enum):
 """Get a (unicode) string representation of a notmuch_status_t 
value."""
 # define strings for custom error messages
 if status == STATUS.NOT_INITIALIZED:
-return u"Operation on uninitialized object impossible."
+return "Operation on uninitialized object impossible."
 return unicode(Status._status2str(status))

 STATUS = Status(['SUCCESS',
@@ -142,7 +142,7 @@ class NotmuchError(Exception):
 elif self.status is not None:
 return STATUS.status2str(self.status)
 else:
-return u'Unknown error'
+return 'Unknown error'


 # List of Subclassed exceptions that correspond to STATUS values and are
-- 
1.7.7.3



[PATCH 2/7] py3k: The ConfigParser module has been renamed to configparser

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch.py  |7 ++-
 bindings/python/notmuch/database.py |8 +++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch.py b/bindings/python/notmuch.py
index 8d11859..3ff53ec 100755
--- a/bindings/python/notmuch.py
+++ b/bindings/python/notmuch.py
@@ -17,7 +17,12 @@ import stat
 import email

 from notmuch import Database, Query, NotmuchError, STATUS
-from ConfigParser import SafeConfigParser
+try:
+# python3.x
+from configparser import SafeConfigParser
+except ImportError:
+# python2.x
+from ConfigParser import SafeConfigParser
 from cStringIO import StringIO

 PREFIX = re.compile('(\w+):(.*$)')
diff --git a/bindings/python/notmuch/database.py 
b/bindings/python/notmuch/database.py
index 7923f76..9318368 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -543,7 +543,13 @@ class Database(object):
 """ Reads a user's notmuch config and returns his db location

 Throws a NotmuchError if it cannot find it"""
-from ConfigParser import SafeConfigParser
+try:
+# python3.x
+from configparser import SafeConfigParser
+except ImportError:
+# python2.x
+from ConfigParser import SafeConfigParser
+
 config = SafeConfigParser()
 conf_f = os.getenv('NOTMUCH_CONFIG',
os.path.expanduser('~/.notmuch-config'))
-- 
1.7.7.3



[PATCH 1/7] py3k: The execfile built-in has been removed in python 3

2011-12-14 Thread Justus Winter
---
 bindings/python/setup.py |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/bindings/python/setup.py b/bindings/python/setup.py
index 286fd19..2e58dab 100644
--- a/bindings/python/setup.py
+++ b/bindings/python/setup.py
@@ -7,7 +7,7 @@ from distutils.core import setup
 # get the notmuch version number without importing the notmuch module
 version_file = os.path.join(os.path.dirname(os.path.abspath(__file__)),
 'notmuch', 'version.py')
-execfile(version_file)
+exec(compile(open(version_file).read(), version_file, 'exec'))
 assert __VERSION__, 'Failed to read the notmuch binding version number'

 setup(name='notmuch',
-- 
1.7.7.3



[python] RFC: supporting python 2 and 3 with one codebase

2011-12-14 Thread Justus Winter
Hi everyone :)

attached is a patch series that makes the notmuch python bindings
compatible with both python 2.x and python 3.x.

There are some workarounds, but those are mostly in globals.py and in
my opinion the benefit of supporting both versions with one codebase
is totally worth it.

Patch seven adds missing unicode conversions that should be applied
even if the rest of the patchset is not.

Cheers,
Justus



[afew] announcing afew, an universal tagging solution with some fancy features

2011-12-14 Thread Justus Winter
Hey everyone :)

I'd like to introduce my initial tagging approach, afew tags:

https://github.com/teythoon/afew

It has some nifty features, citing the README:

* text classification, magic tags aka the mailing list without server
* spam handling (flush all tags, add spam)
* killed thread handling
* tags posts to lists with lists, $list-id
* autoarchives mails sent from you
* catchall -> remove new, add inbox
* can operate on new messages [default], --all messages or on custom
  query results
* has a --dry-run mode for safe testing
* works with both python2.7 and python3.2

Eagerly waiting for your feedback and patches ;)
Justus
-- next part --
A non-text attachment was scrubbed...
Name: .signature
Type: application/octet-stream
Size: 17 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20111214/f8bd5a9c/attachment.obj>


[afew] announcing afew,

2011-12-14 Thread Kazuo Teramoto
an universal tagging solution with some fancy features
From: Kazuo Teramoto 
In-Reply-To: 
On 2011-12-14T08:42:36, Justus Winter wrote:
>I'd like to introduce my initial tagging approach, afew tags:
>
>https://github.com/teythoon/afew
>

Very good! Thanks for it. I'm using it as my only filtering/tagging
solutions and works great.

I created a Arch Linux PKGBUILD, it can be find at [aur] (about it,
Justus how you define the afew license? I put a 'unknown' in the license
as I can give it a names like BSD or GPL or WTFPL).

>* works with both python2.7 and python3.2
>

Python 3 support need the patch set you send to the list, correct?

Regards,
Kazuo

[aur]: https://aur.archlinux.org/packages.php?ID=54532



[PATCH v6 1/2] emacs: User-defined sections in notmuch-hello

2011-12-14 Thread Dmitry Kurochkin
Hi Daniel.

I have finished reviewing this patch at last.  Sorry, it is a bit messy.
Overall, I like the patch.  It is a very nice improvement.

I am sure I have missed some important points, but I guess this is the
best I can do right now.  Perhaps I will find more comments for the next
version of the patch :)

As we already discussed on IRC, there are some trailing whitespaces to
cleanup.

Here is the review:

+(defvar notmuch-custom-section-options

s/notmuch-custom-section-options/notmuch-hello-custom-section-options/ for 
consistency?

+(:filter-count (string :tag "Different filter message counts"))

It was not clear to me what this option is for from the docstring.
Perhaps something like: "Count query filter, if different from :filter"?

+(:initially-hidden (const :tag "Hide this on startup?" t))

"This" refers to section, right?  If yes, let's state it explicitly:
"Hide this section on startup".  Also, we should probably remove the
question mark, or add it to other options for consistency.

Should the default be to show all sections?

+(:hide-if-empty (const :tag "Hide if empty" t)))

As I understand, this controls whether the whole sections is visible.
It is not clear what "if empty" means.  Does it mean that all queries
are empty?  Or all queries are empty and :show-empty-sections is
false?  Consider changing to something like: "Hide this section if all
queries are empty [and hidden]".

+  `(list :tag ""
+(const :tag "" notmuch-hello-insert-query-list)

Do we need to explicitly specify empty tags?  Aren't they empty by
default?

+  :tag "Customized tag-list (see docstring for details)"
+  :tag "Customized queries section (see docstring for details)"

Perhaps it would be more useful to add reference to
`notmuch-hello-sections'?  I.e. "see `notmuch-hello-sections' for
details.

Please s/Customized tag-list/Customized tag-list section/ everywhere for
consistency (or remove section from "Customized queries section").

+Each entry of this list should be a function of no arguments that
+should return if `notmuch-hello-target' is produced as part of its
+output and nil otherwise.

Something is missing between "return if".  IMO it is really hard to
understand what the function should actually do and what it should
return.  Are this functions expected to add section content to current
position?  As I understand, the return value indicates whether cursor
should be positioned somewhere inside this section.  It is a minor
detail, but it is described in the first (and complex sentence) as if
it was the most important part.  Consider moving the return and "no
arguments" to the 3rd paragraph which describes details about the
functions.  I would also swap 2nd and 3rd paragraph.  Smth like:

  The list contains functions which are used to construct sections in
  notmuch-hello buffer.  When notmuch-hello buffer is constructed,
  these functions are run in the order they appear in this list.  Each
  function produces a section simply by adding content to the current
  buffer.  A section should not end with an empty line, because a
  newline will be inserted after each section by `notmuch-hello'.

  Each function should take no arguments.  If the produced section
  includes `notmuch-hello-target' (i.e. cursor should be positioned
  inside this section), the function should return [something].
  Otherwise, it should return nil.

  For convenience an element can also be a list of the form (FUNC ARG1
  ARG2 .. ARGN) in which case FUNC will be applied to the rest of the
  list.

  [ details about customized tag-list and queries sections ]

This is just a draft.  Feel free to use it or ignore it.

+ For convenience an element can also be

Remove space the leading space and do `fill-paragraph'.

+   (function :tag "Custom function"

Perhaps "Custom section" would be more accurate?

+  "Button at position of point before rebuilding the notmuch-buffer

Missing dot at the end.

s/Button/Button text/?

+This variable contains the string of the button, if any, the

s/the string/text/ or label?

+rebuilt. This is never actually set globally and defined as a

s/is never actually set/should never be set/?

+(defvar notmuch-hello-hidden-sections nil
+  "List of query section titles whose contents are hidden")

Is this really for query sections only?

Does this duplicate :initially-hidden option from
notmuch-custom-section-options?

How about adding a global alist variable notmuch-hello-state to store
the state needed for section functions?  Currently, it would contain
two values: :first-run and :target.  This would allow us to add more
state variables in the future without polluting the global namespace.
Also, it would make clear what variables are section function are
supposed to use and perhaps even change (docstring should explain that
of course).

`notmuch-hello-filtered-query':

+  (and result (concat query " and (" result ")"

How about using the result as query instead of filter?  

[PATCH] test: optionally print subtest number

2011-12-14 Thread Dmitry Kurochkin
On Tue, 13 Dec 2011 15:35:53 -0800, Jameson Graef Rollins  wrote:
> On Wed, 14 Dec 2011 03:24:23 +0400, Dmitry Kurochkin  gmail.com> wrote:
> > BTW I have some plans to introduce optional explicit test ids that can
> > be used for inter-test dependencies.  E.g.:
> > 
> >   test_begin_subtest test-id-1 "A subtest"
> >   
> >   ;; in another test requre that test-id-1 passed
> >   test_require_subtest test-id-1
> 
> Would the required test need to be listed twice, both on the
> begin_subtest line *and* in the require_subtest line?
> 
> And again, why would the test id have to be any different that the
> existing test names?  The tests already have names, so I don't
> understand why we would want to introduce some other kind of
> identification.  Seems like it's just going to add extra confusion.
> 

What you listed in the other email are test scripts, each with many
subtests.  I was talking about dependencies between subtests, not test
scripts.

> And speaking of which, I sometimes worry that the test infrastructure
> itself is getting too complicated.  Pretty soon we're going to need
> tests for the tests.

We already have them :)  Though, pretty limited.

>  I don't necessarily see the need to all of these
> extra features in the test suite, so I worry that it's just making
> everything harder to debug.
> 

I hope we can keep balance here.

Without inter-subtest dependencies, we have unhealthy situation where
some tests may be skipped because of missing prerequisites, but test
that depend on them are failing.  The only alternative I see is to
rewrite these tests to remove the dependencies.  But that would
complicate test cases itself, so I believe inter-subtest dependencies is
a better option.

Regards,
  Dmitry

> jamie.


[PATCH] test: optionally print subtest number

2011-12-14 Thread Dmitry Kurochkin
On Tue, 13 Dec 2011 19:18:16 -0400, David Bremner  wrote:
> On Tue, 13 Dec 2011 14:22:21 -0800, Jameson Graef Rollins  finestructure.net> wrote:
> 
> > I've only been vaguely following this "test count" stuff, but I'm not
> > sure I understand what's the point of giving tests a number that is
> > ultimately mutable.  Why not just label things by the test name, instead
> > of the count?  That wouldn't require keeping track of number/name
> > mapping, which will change over time.
> 
> We don't actually have test names, at least not ones directly suitable
> for file names.  I guess we could encode them or something, is that what
> you mean?
> 

BTW I have some plans to introduce optional explicit test ids that can
be used for inter-test dependencies.  E.g.:

  test_begin_subtest test-id-1 "A subtest"
  
  ;; in another test requre that test-id-1 passed
  test_require_subtest test-id-1

Regards,
  Dmitry

> d
> ___
> notmuch mailing list
> notmuch at notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH] test: optionally print subtest number

2011-12-14 Thread Dmitry Kurochkin
On Tue, 13 Dec 2011 22:55:18 +0200, Tomi Ollila  wrote:
> On Wed, 14 Dec 2011 00:15:43 +0400, Dmitry Kurochkin  gmail.com> wrote:
> > On Tue, 13 Dec 2011 15:56:47 -0400, David Bremner  
> > wrote:
> > > From: David Bremner 
> > > 
> > > The idea is that $test_count could be used in tests to label
> > > intermediate files. The output enabled by this patch (and --debug)
> > > helps figure out which OUTPUT.nn file belongs to which test in case
> > > several subtests write to OUTPUT.$test_count
> > > ---
> > > 
> > > Is there something that depends on the test format? I find it pretty
> > > handy to have the subtest numbers, but I don't want to break some
> > > other tools. I followed the existing style of conditionally defining
> > > functions, but maybe someone with more bash-fu can improve that.
> > > 
> > 
> > Looks good to me.  Except for tabs taking too much space.  Perhaps the
> > following would be better?
> > 
> > printf "%-4s" "[$(($test_count - 1))]"
> 
> I attempted the same size reduction. Therefore I know that
> this should to be either
> 
>   printf " %-4s" "[$(($test_count - 1))]"
> or
>   printf "\t%-4s" "[$(($test_count - 1))]"
> 
> (or something similar) so that there is space betweem BROKEN and [num]
> 

Oh, apparently, not enough testing on my side.

I vote for the first version with a space.

Regards,
  Dmitry

> This takes 4 bytes out from width (and drops tab as field separator)
> (and only few lines goes over 80 char width (some goes even with this
> reduction). So ...
> 
> 
> > Regards,
> >   Dmitry
> 
> Tomi
> 


[PATCH] test: optionally print subtest number

2011-12-14 Thread Dmitry Kurochkin
On Tue, 13 Dec 2011 15:56:47 -0400, David Bremner  wrote:
> From: David Bremner 
> 
> The idea is that $test_count could be used in tests to label
> intermediate files. The output enabled by this patch (and --debug)
> helps figure out which OUTPUT.nn file belongs to which test in case
> several subtests write to OUTPUT.$test_count
> ---
> 
> Is there something that depends on the test format? I find it pretty
> handy to have the subtest numbers, but I don't want to break some
> other tools. I followed the existing style of conditionally defining
> functions, but maybe someone with more bash-fu can improve that.
> 

Looks good to me.  Except for tabs taking too much space.  Perhaps the
following would be better?

printf "%-4s" "[$(($test_count - 1))]"

Regards,
  Dmitry

>  test/test-lib.sh |   12 
>  1 files changed, 12 insertions(+), 0 deletions(-)
> 
> diff --git a/test/test-lib.sh b/test/test-lib.sh
> index 6be93fe..f5c 100644
> --- a/test/test-lib.sh
> +++ b/test/test-lib.sh
> @@ -116,6 +116,16 @@ do
>   esac
>  done
>  
> +if test -n "$debug"; then
> +print_subtest () {
> + printf "\t[%d]\t" $(($test_count - 1))
> +}
> +else
> +print_subtest () {
> + true
> +}
> +fi
> +
>  if test -n "$color"; then
>   say_color () {
>   (
> @@ -132,6 +142,7 @@ if test -n "$color"; then
>   printf " "
>  printf "$@"
>   tput sgr0
> + print_subtest
>   )
>   }
>  else
> @@ -140,6 +151,7 @@ else
>   shift
>   printf " "
>  printf "$@"
> + print_subtest
>   }
>  fi
>  
> -- 
> 1.7.5.4
> 
> ___
> notmuch mailing list
> notmuch at notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch


[afew] announcing afew, an universal tagging solution with some fancy features

2011-12-14 Thread Justus Winter
Hey everyone :)

I'd like to introduce my initial tagging approach, afew tags:

https://github.com/teythoon/afew

It has some nifty features, citing the README:

* text classification, magic tags aka the mailing list without server
* spam handling (flush all tags, add spam)
* killed thread handling
* tags posts to lists with lists, $list-id
* autoarchives mails sent from you
* catchall - remove new, add inbox
* can operate on new messages [default], --all messages or on custom
  query results
* has a --dry-run mode for safe testing
* works with both python2.7 and python3.2

Eagerly waiting for your feedback and patches ;)
Justus


.signature
Description: Binary data
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 1/7] py3k: The execfile built-in has been removed in python 3

2011-12-14 Thread Justus Winter
---
 bindings/python/setup.py |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/bindings/python/setup.py b/bindings/python/setup.py
index 286fd19..2e58dab 100644
--- a/bindings/python/setup.py
+++ b/bindings/python/setup.py
@@ -7,7 +7,7 @@ from distutils.core import setup
 # get the notmuch version number without importing the notmuch module
 version_file = os.path.join(os.path.dirname(os.path.abspath(__file__)),
 'notmuch', 'version.py')
-execfile(version_file)
+exec(compile(open(version_file).read(), version_file, 'exec'))
 assert __VERSION__, 'Failed to read the notmuch binding version number'
 
 setup(name='notmuch',
-- 
1.7.7.3

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 2/7] py3k: The ConfigParser module has been renamed to configparser

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch.py  |7 ++-
 bindings/python/notmuch/database.py |8 +++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch.py b/bindings/python/notmuch.py
index 8d11859..3ff53ec 100755
--- a/bindings/python/notmuch.py
+++ b/bindings/python/notmuch.py
@@ -17,7 +17,12 @@ import stat
 import email
 
 from notmuch import Database, Query, NotmuchError, STATUS
-from ConfigParser import SafeConfigParser
+try:
+# python3.x
+from configparser import SafeConfigParser
+except ImportError:
+# python2.x
+from ConfigParser import SafeConfigParser
 from cStringIO import StringIO
 
 PREFIX = re.compile('(\w+):(.*$)')
diff --git a/bindings/python/notmuch/database.py 
b/bindings/python/notmuch/database.py
index 7923f76..9318368 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -543,7 +543,13 @@ class Database(object):
  Reads a user's notmuch config and returns his db location
 
 Throws a NotmuchError if it cannot find it
-from ConfigParser import SafeConfigParser
+try:
+# python3.x
+from configparser import SafeConfigParser
+except ImportError:
+# python2.x
+from ConfigParser import SafeConfigParser
+
 config = SafeConfigParser()
 conf_f = os.getenv('NOTMUCH_CONFIG',
os.path.expanduser('~/.notmuch-config'))
-- 
1.7.7.3

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 3/7] py3k: All strings are unicode strings in py3k

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/globals.py |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch/globals.py 
b/bindings/python/notmuch/globals.py
index 54a49b2..99e6a10 100644
--- a/bindings/python/notmuch/globals.py
+++ b/bindings/python/notmuch/globals.py
@@ -51,7 +51,7 @@ class Status(Enum):
 Get a (unicode) string representation of a notmuch_status_t 
value.
 # define strings for custom error messages
 if status == STATUS.NOT_INITIALIZED:
-return uOperation on uninitialized object impossible.
+return Operation on uninitialized object impossible.
 return unicode(Status._status2str(status))
 
 STATUS = Status(['SUCCESS',
@@ -142,7 +142,7 @@ class NotmuchError(Exception):
 elif self.status is not None:
 return STATUS.status2str(self.status)
 else:
-return u'Unknown error'
+return 'Unknown error'
 
 
 # List of Subclassed exceptions that correspond to STATUS values and are
-- 
1.7.7.3

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 5/7] py3k: the basestring and unicode types are removed in python 3

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/globals.py |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch/globals.py 
b/bindings/python/notmuch/globals.py
index 99e6a10..c52790c 100644
--- a/bindings/python/notmuch/globals.py
+++ b/bindings/python/notmuch/globals.py
@@ -17,6 +17,7 @@ along with notmuch.  If not, see 
http://www.gnu.org/licenses/.
 Copyright 2010 Sebastian Spaeth sebast...@sspaeth.de'
 
 
+import sys
 from ctypes import CDLL, c_char_p, c_int, Structure, POINTER
 
 #-
@@ -200,9 +201,9 @@ def _str(value):
 
 C++ code expects strings to be well formatted and
 unicode strings to have no null bytes.
-if not isinstance(value, basestring):
+if not isinstance(value, basestring if sys.version_info[0] == 2 else str):
 raise TypeError(Expected str or unicode, got %s % str(type(value)))
-if isinstance(value, unicode):
+if sys.version_info[0] == 3 or isinstance(value, unicode):
 return value.encode('UTF-8')
 return value
 
-- 
1.7.7.3

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 4/7] py3k: Rename .next() to __next__(), add python2.x compatibility alias

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/database.py |3 ++-
 bindings/python/notmuch/message.py  |3 ++-
 bindings/python/notmuch/tag.py  |3 ++-
 bindings/python/notmuch/thread.py   |3 ++-
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/bindings/python/notmuch/database.py 
b/bindings/python/notmuch/database.py
index 9318368..3f6e04d 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -925,7 +925,7 @@ class Filenames(object):
 _move_to_next.argtypes = [NotmuchFilenamesP]
 _move_to_next.restype = None
 
-def next(self):
+def __next__(self):
 if self._files_p is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
 
@@ -936,6 +936,7 @@ class Filenames(object):
 file = Filenames._get(self._files_p)
 self._move_to_next(self._files_p)
 return file
+next = __next__ # python2.x iterator protocol compatibility
 
 def __len__(self):
 len(:class:`Filenames`) returns the number of contained files
diff --git a/bindings/python/notmuch/message.py 
b/bindings/python/notmuch/message.py
index ce8e718..bf0c4da 100644
--- a/bindings/python/notmuch/message.py
+++ b/bindings/python/notmuch/message.py
@@ -158,7 +158,7 @@ class Messages(object):
 _move_to_next.argtypes = [NotmuchMessagesP]
 _move_to_next.restype = None
 
-def next(self):
+def __next__(self):
 if self._msgs is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
 
@@ -169,6 +169,7 @@ class Messages(object):
 msg = Message(Messages._get(self._msgs), self)
 self._move_to_next(self._msgs)
 return msg
+next = __next__ # python2.x iterator protocol compatibility
 
 def __nonzero__(self):
 
diff --git a/bindings/python/notmuch/tag.py b/bindings/python/notmuch/tag.py
index 2fb7d32..d42ba77 100644
--- a/bindings/python/notmuch/tag.py
+++ b/bindings/python/notmuch/tag.py
@@ -89,7 +89,7 @@ class Tags(object):
 _move_to_next.argtypes = [NotmuchTagsP]
 _move_to_next.restype = None
 
-def next(self):
+def __next__(self):
 if self._tags is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
 if not self._valid(self._tags):
@@ -98,6 +98,7 @@ class Tags(object):
 tag = Tags._get(self._tags).decode('UTF-8')
 self._move_to_next(self._tags)
 return tag
+next = __next__ # python2.x iterator protocol compatibility
 
 def __nonzero__(self):
 Implement bool(Tags) check that can be repeatedly used
diff --git a/bindings/python/notmuch/thread.py 
b/bindings/python/notmuch/thread.py
index 5058846..39285d6 100644
--- a/bindings/python/notmuch/thread.py
+++ b/bindings/python/notmuch/thread.py
@@ -116,7 +116,7 @@ class Threads(object):
 _move_to_next.argtypes = [NotmuchThreadsP]
 _move_to_next.restype = None
 
-def next(self):
+def __next__(self):
 if self._threads is None:
 raise NotmuchError(STATUS.NOT_INITIALIZED)
 
@@ -127,6 +127,7 @@ class Threads(object):
 thread = Thread(Threads._get(self._threads), self)
 self._move_to_next(self._threads)
 return thread
+next = __next__ # python2.x iterator protocol compatibility
 
 def __len__(self):
 len(:class:`Threads`) returns the number of contained Threads
-- 
1.7.7.3

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 6/7] py3k: Add and use a mixin class that implements __str__

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/filename.py |7 ++-
 bindings/python/notmuch/globals.py  |   15 +++
 bindings/python/notmuch/message.py  |8 +++-
 bindings/python/notmuch/tag.py  |7 ++-
 bindings/python/notmuch/thread.py   |6 +++---
 5 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/bindings/python/notmuch/filename.py 
b/bindings/python/notmuch/filename.py
index a7cd7e6..969931a 100644
--- a/bindings/python/notmuch/filename.py
+++ b/bindings/python/notmuch/filename.py
@@ -18,10 +18,10 @@ Copyright 2010 Sebastian Spaeth sebast...@sspaeth.de'
 
 from ctypes import c_char_p
 from notmuch.globals import (nmlib, STATUS, NotmuchError,
-NotmuchFilenamesP, NotmuchMessageP)
+NotmuchFilenamesP, NotmuchMessageP, _str, Python3StringMixIn)
 
 
-class Filenames(object):
+class Filenames(Python3StringMixIn):
 Represents a list of filenames as returned by notmuch
 
 This object contains the Filenames iterator. The main function is
@@ -98,9 +98,6 @@ class Filenames(object):
 
 self._files = None
 
-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 Represent Filenames() as newline-separated list of full paths
 
diff --git a/bindings/python/notmuch/globals.py 
b/bindings/python/notmuch/globals.py
index c52790c..2111b86 100644
--- a/bindings/python/notmuch/globals.py
+++ b/bindings/python/notmuch/globals.py
@@ -28,6 +28,16 @@ except:
 raise ImportError(Could not find shared 'notmuch' library.)
 
 
+if sys.version_info[0] == 2:
+class Python3StringMixIn(object):
+def __str__(self):
+return unicode(self).encode('utf-8')
+else:
+class Python3StringMixIn(object):
+def __str__(self):
+return self.__unicode__()
+
+
 class Enum(object):
 Provides ENUMS as code=Enum(['a','b','c']) where code.a=0 etc...
 def __init__(self, names):
@@ -90,7 +100,7 @@ argument to receive a human readable string
 STATUS.__name__ = 'STATUS'
 
 
-class NotmuchError(Exception):
+class NotmuchError(Exception, Python3StringMixIn):
 Is initiated with a (notmuch.STATUS[, message=None]). It will not
 return an instance of the class NotmuchError, but a derived instance
 of a more specific Error Message, e.g. OutOfMemoryError. Each status
@@ -134,9 +144,6 @@ class NotmuchError(Exception):
 self.status = status
 self.message = message
 
-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 if self.message is not None:
 return self.message
diff --git a/bindings/python/notmuch/message.py 
b/bindings/python/notmuch/message.py
index bf0c4da..955382d 100644
--- a/bindings/python/notmuch/message.py
+++ b/bindings/python/notmuch/message.py
@@ -21,7 +21,8 @@ Copyright 2010 Sebastian Spaeth sebast...@sspaeth.de'
 
 from ctypes import c_char_p, c_long, c_uint, c_int
 from datetime import date
-from notmuch.globals import (nmlib, STATUS, NotmuchError, Enum, _str,
+from notmuch.globals import (
+nmlib, STATUS, NotmuchError, Enum, _str, Python3StringMixIn,
 NotmuchTagsP, NotmuchMessagesP, NotmuchMessageP, NotmuchFilenamesP)
 from notmuch.tag import Tags
 from notmuch.filename import Filenames
@@ -239,7 +240,7 @@ class Messages(object):
 sys.stdout.write(set_end)
 
 
-class Message(object):
+class Message(Python3StringMixIn):
 Represents a single Email message
 
 Technically, this wraps the underlying *notmuch_message_t*
@@ -796,9 +797,6 @@ class Message(object):
 Represent a Message() object by str()
 return self.__str__()
 
-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 format = %s (%s) (%s)
 return format % (self.get_header('from'),
diff --git a/bindings/python/notmuch/tag.py b/bindings/python/notmuch/tag.py
index d42ba77..ceb7244 100644
--- a/bindings/python/notmuch/tag.py
+++ b/bindings/python/notmuch/tag.py
@@ -17,10 +17,10 @@ along with notmuch.  If not, see 
http://www.gnu.org/licenses/.
 Copyright 2010 Sebastian Spaeth sebast...@sspaeth.de'
 
 from ctypes import c_char_p
-from notmuch.globals import nmlib, STATUS, NotmuchError, NotmuchTagsP
+from notmuch.globals import nmlib, STATUS, NotmuchError, NotmuchTagsP, _str, 
Python3StringMixIn
 
 
-class Tags(object):
+class Tags(Python3StringMixIn):
 Represents a list of notmuch tags
 
 This object provides an iterator over a list of notmuch tags (which
@@ -111,9 +111,6 @@ class Tags(object):
 left.
 return self._valid(self._tags)  0
 
-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 string representation of :class:`Tags`: a space separated list of 
tags
 
diff --git a/bindings/python/notmuch/thread.py 
b/bindings/python/notmuch/thread.py
index 39285d6..3912957 100644
--- a/bindings/python/notmuch/thread.py
+++ 

Re: [afew] announcing afew,

2011-12-14 Thread Kazuo Teramoto
an universal tagging solution with some fancy features
From: Kazuo Teramoto kaz@gmail.com
In-Reply-To: e1ramig-0003si...@thinkbox.jade-hamburg.de
On 2011-12-14T08:42:36, Justus Winter wrote:
I'd like to introduce my initial tagging approach, afew tags:

https://github.com/teythoon/afew


Very good! Thanks for it. I'm using it as my only filtering/tagging
solutions and works great.

I created a Arch Linux PKGBUILD, it can be find at [aur] (about it,
Justus how you define the afew license? I put a 'unknown' in the license
as I can give it a names like BSD or GPL or WTFPL).

* works with both python2.7 and python3.2


Python 3 support need the patch set you send to the list, correct?

Regards,
Kazuo

[aur]: https://aur.archlinux.org/packages.php?ID=54532

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 3/7] py3k: All strings are unicode strings in py3k

2011-12-14 Thread Tomi Ollila
On Wed, 14 Dec 2011 11:58:21 +0100, Justus Winter 
4win...@informatik.uni-hamburg.de wrote:
 ---
  bindings/python/notmuch/globals.py |4 ++--
  1 files changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/bindings/python/notmuch/globals.py 
 b/bindings/python/notmuch/globals.py
 index 54a49b2..99e6a10 100644
 --- a/bindings/python/notmuch/globals.py
 +++ b/bindings/python/notmuch/globals.py
 @@ -51,7 +51,7 @@ class Status(Enum):
  Get a (unicode) string representation of a notmuch_status_t 
 value.
  # define strings for custom error messages
  if status == STATUS.NOT_INITIALIZED:
 -return uOperation on uninitialized object impossible.
 +return Operation on uninitialized object impossible.
  return unicode(Status._status2str(status))
  
  STATUS = Status(['SUCCESS',
 @@ -142,7 +142,7 @@ class NotmuchError(Exception):
  elif self.status is not None:
  return STATUS.status2str(self.status)
  else:
 -return u'Unknown error'
 +return 'Unknown error'

Is this u -prefix unnecessary in python 2 too ? Grepping
'u' and u' in **/*.py in puthon bindings source resulted
some more u-prefixed strings in docs/source/conf.py. Should
these be changed in some future patch ?

  # List of Subclassed exceptions that correspond to STATUS values and are
 -- 
 1.7.7.3

Tomi
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 6/7] py3k: Add and use a mixin class that implements __str__

2011-12-14 Thread Tomi Ollila
On Wed, 14 Dec 2011 11:58:24 +0100, Justus Winter 
4win...@informatik.uni-hamburg.de wrote:
 ---
[ ... snip ... ]

  
 -class Filenames(object):
 +class Filenames(Python3StringMixIn):
  Represents a list of filenames as returned by notmuch
  
  This object contains the Filenames iterator. The main function is
 @@ -98,9 +98,6 @@ class Filenames(object):
  
  self._files = None
  
 -def __str__(self):
 -return unicode(self).encode('utf-8')
 -
  def __unicode__(self):
  Represent Filenames() as newline-separated list of full paths
  
 diff --git a/bindings/python/notmuch/globals.py 
 b/bindings/python/notmuch/globals.py
 index c52790c..2111b86 100644
 --- a/bindings/python/notmuch/globals.py
 +++ b/bindings/python/notmuch/globals.py
 @@ -28,6 +28,16 @@ except:
  raise ImportError(Could not find shared 'notmuch' library.)
  
  
 +if sys.version_info[0] == 2:
 +class Python3StringMixIn(object):
 +def __str__(self):
 +return unicode(self).encode('utf-8')
 +else:
 +class Python3StringMixIn(object):
 +def __str__(self):
 +return self.__unicode__()
 +
 +

[ ... snip ... ]

 -class Threads(object):
 +class Threads(Python3StringMixIn):
  Represents a list of notmuch threads
  
  This object provides an iterator over a list of notmuch threads
 @@ -393,7 +393,7 @@ class Thread(object):
  return Tags(tags_p, self)
  
  def __str__(self):
 -return unicode(self).encode('utf-8')
 +return self.__unicode__().encode('utf-8')
  
  def __unicode__(self):
  frm = thread:%s %12s [%d/%d] %s; %s (%s)

Is this class special case ? in all other classes
the __str__() function has been removed (using inherited
function) ?

 -- 
 1.7.7.3

Otherwise LGTM -- pretty simple and effective (all 7 patches).

Tomi

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v6 1/2] emacs: User-defined sections in notmuch-hello

2011-12-14 Thread Dmitry Kurochkin
On Wed, 14 Dec 2011 07:11:21 +0400, Dmitry Kurochkin 
dmitry.kuroch...@gmail.com wrote:
 Hi Daniel.
 
 I have finished reviewing this patch at last.  Sorry, it is a bit messy.
 Overall, I like the patch.  It is a very nice improvement.
 
 I am sure I have missed some important points, but I guess this is the
 best I can do right now.  Perhaps I will find more comments for the next
 version of the patch :)
 
 As we already discussed on IRC, there are some trailing whitespaces to
 cleanup.
 
 Here is the review:
 
 +(defvar notmuch-custom-section-options
 
 s/notmuch-custom-section-options/notmuch-hello-custom-section-options/ for 
 consistency?
 
 +(:filter-count (string :tag Different filter message counts))
 
 It was not clear to me what this option is for from the docstring.
 Perhaps something like: Count query filter, if different from :filter?
 
 +(:initially-hidden (const :tag Hide this on startup? t))
 
 This refers to section, right?  If yes, let's state it explicitly:
 Hide this section on startup.  Also, we should probably remove the
 question mark, or add it to other options for consistency.
 
 Should the default be to show all sections?
 
 +(:hide-if-empty (const :tag Hide if empty t)))
 
 As I understand, this controls whether the whole sections is visible.
 It is not clear what if empty means.  Does it mean that all queries
 are empty?  Or all queries are empty and :show-empty-sections is
 false?  Consider changing to something like: Hide this section if all
 queries are empty [and hidden].
 
 +  `(list :tag 
 +  (const :tag  notmuch-hello-insert-query-list)
 
 Do we need to explicitly specify empty tags?  Aren't they empty by
 default?
 
 +  :tag Customized tag-list (see docstring for details)
 +  :tag Customized queries section (see docstring for details)
 
 Perhaps it would be more useful to add reference to
 `notmuch-hello-sections'?  I.e. see `notmuch-hello-sections' for
 details.
 
 Please s/Customized tag-list/Customized tag-list section/ everywhere for
 consistency (or remove section from Customized queries section).
 
 +Each entry of this list should be a function of no arguments that
 +should return if `notmuch-hello-target' is produced as part of its
 +output and nil otherwise.
 
 Something is missing between return if.  IMO it is really hard to
 understand what the function should actually do and what it should
 return.  Are this functions expected to add section content to current
 position?  As I understand, the return value indicates whether cursor
 should be positioned somewhere inside this section.  It is a minor
 detail, but it is described in the first (and complex sentence) as if
 it was the most important part.  Consider moving the return and no
 arguments to the 3rd paragraph which describes details about the
 functions.  I would also swap 2nd and 3rd paragraph.  Smth like:
 
   The list contains functions which are used to construct sections in
   notmuch-hello buffer.  When notmuch-hello buffer is constructed,
   these functions are run in the order they appear in this list.  Each
   function produces a section simply by adding content to the current
   buffer.  A section should not end with an empty line, because a
   newline will be inserted after each section by `notmuch-hello'.
 
   Each function should take no arguments.  If the produced section
   includes `notmuch-hello-target' (i.e. cursor should be positioned
   inside this section), the function should return [something].
   Otherwise, it should return nil.
 
   For convenience an element can also be a list of the form (FUNC ARG1
   ARG2 .. ARGN) in which case FUNC will be applied to the rest of the
   list.
 
   [ details about customized tag-list and queries sections ]
 
 This is just a draft.  Feel free to use it or ignore it.
 
 + For convenience an element can also be
 
 Remove space the leading space and do `fill-paragraph'.
 
 + (function :tag Custom function
 
 Perhaps Custom section would be more accurate?
 
 +  Button at position of point before rebuilding the notmuch-buffer
 
 Missing dot at the end.
 
 s/Button/Button text/?
 
 +This variable contains the string of the button, if any, the
 
 s/the string/text/ or label?
 
 +rebuilt. This is never actually set globally and defined as a
 
 s/is never actually set/should never be set/?
 
 +(defvar notmuch-hello-hidden-sections nil
 +  List of query section titles whose contents are hidden)
 
 Is this really for query sections only?
 
 Does this duplicate :initially-hidden option from
 notmuch-custom-section-options?
 
 How about adding a global alist variable notmuch-hello-state to store
 the state needed for section functions?  Currently, it would contain
 two values: :first-run and :target.  This would allow us to add more
 state variables in the future without polluting the global namespace.
 Also, it would make clear what variables are section function are
 supposed to use and perhaps even change (docstring should 

Re: [PATCH 6/7] py3k: Add and use a mixin class that implements __str__

2011-12-14 Thread Justus Winter
Quoting Tomi Ollila (2011-12-14 13:26:38)
On Wed, 14 Dec 2011 11:58:24 +0100, Justus Winter 
4win...@informatik.uni-hamburg.de wrote:
 ---
[ ... snip ... ]

  
 -class Filenames(object):
 +class Filenames(Python3StringMixIn):
  Represents a list of filenames as returned by notmuch
  
  This object contains the Filenames iterator. The main function is
 @@ -98,9 +98,6 @@ class Filenames(object):
  
  self._files = None
  
 -def __str__(self):
 -return unicode(self).encode('utf-8')
 -
  def __unicode__(self):
  Represent Filenames() as newline-separated list of full paths
  
 diff --git a/bindings/python/notmuch/globals.py 
 b/bindings/python/notmuch/globals.py
 index c52790c..2111b86 100644
 --- a/bindings/python/notmuch/globals.py
 +++ b/bindings/python/notmuch/globals.py
 @@ -28,6 +28,16 @@ except:
  raise ImportError(Could not find shared 'notmuch' library.)
  
  
 +if sys.version_info[0] == 2:
 +class Python3StringMixIn(object):
 +def __str__(self):
 +return unicode(self).encode('utf-8')
 +else:
 +class Python3StringMixIn(object):
 +def __str__(self):
 +return self.__unicode__()
 +
 +

[ ... snip ... ]

 -class Threads(object):
 +class Threads(Python3StringMixIn):
  Represents a list of notmuch threads
  
  This object provides an iterator over a list of notmuch threads
 @@ -393,7 +393,7 @@ class Thread(object):
  return Tags(tags_p, self)
  
  def __str__(self):
 -return unicode(self).encode('utf-8')
 +return self.__unicode__().encode('utf-8')
  
  def __unicode__(self):
  frm = thread:%s %12s [%d/%d] %s; %s (%s)

Is this class special case ? in all other classes
the __str__() function has been removed (using inherited
function) ?

Damn, I missed that one... that was my first approach but that
obviously didn't worked out... I'll send an updated patch.

Otherwise LGTM -- pretty simple and effective (all 7 patches).

Thanks :)

Note that I do not know how complete the port is. But the stuff used
by my tagging application (afew) works.

Justus


.signature
Description: Binary data
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 6/7] py3k: Add and use a mixin class that implements __str__

2011-12-14 Thread Justus Winter
---
 bindings/python/notmuch/filename.py |7 ++-
 bindings/python/notmuch/globals.py  |   15 +++
 bindings/python/notmuch/message.py  |8 +++-
 bindings/python/notmuch/tag.py  |7 ++-
 bindings/python/notmuch/thread.py   |7 ++-
 5 files changed, 20 insertions(+), 24 deletions(-)

diff --git a/bindings/python/notmuch/filename.py 
b/bindings/python/notmuch/filename.py
index a7cd7e6..969931a 100644
--- a/bindings/python/notmuch/filename.py
+++ b/bindings/python/notmuch/filename.py
@@ -18,10 +18,10 @@ Copyright 2010 Sebastian Spaeth sebast...@sspaeth.de'
 
 from ctypes import c_char_p
 from notmuch.globals import (nmlib, STATUS, NotmuchError,
-NotmuchFilenamesP, NotmuchMessageP)
+NotmuchFilenamesP, NotmuchMessageP, _str, Python3StringMixIn)
 
 
-class Filenames(object):
+class Filenames(Python3StringMixIn):
 Represents a list of filenames as returned by notmuch
 
 This object contains the Filenames iterator. The main function is
@@ -98,9 +98,6 @@ class Filenames(object):
 
 self._files = None
 
-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 Represent Filenames() as newline-separated list of full paths
 
diff --git a/bindings/python/notmuch/globals.py 
b/bindings/python/notmuch/globals.py
index c52790c..2111b86 100644
--- a/bindings/python/notmuch/globals.py
+++ b/bindings/python/notmuch/globals.py
@@ -28,6 +28,16 @@ except:
 raise ImportError(Could not find shared 'notmuch' library.)
 
 
+if sys.version_info[0] == 2:
+class Python3StringMixIn(object):
+def __str__(self):
+return unicode(self).encode('utf-8')
+else:
+class Python3StringMixIn(object):
+def __str__(self):
+return self.__unicode__()
+
+
 class Enum(object):
 Provides ENUMS as code=Enum(['a','b','c']) where code.a=0 etc...
 def __init__(self, names):
@@ -90,7 +100,7 @@ argument to receive a human readable string
 STATUS.__name__ = 'STATUS'
 
 
-class NotmuchError(Exception):
+class NotmuchError(Exception, Python3StringMixIn):
 Is initiated with a (notmuch.STATUS[, message=None]). It will not
 return an instance of the class NotmuchError, but a derived instance
 of a more specific Error Message, e.g. OutOfMemoryError. Each status
@@ -134,9 +144,6 @@ class NotmuchError(Exception):
 self.status = status
 self.message = message
 
-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 if self.message is not None:
 return self.message
diff --git a/bindings/python/notmuch/message.py 
b/bindings/python/notmuch/message.py
index bf0c4da..955382d 100644
--- a/bindings/python/notmuch/message.py
+++ b/bindings/python/notmuch/message.py
@@ -21,7 +21,8 @@ Copyright 2010 Sebastian Spaeth sebast...@sspaeth.de'
 
 from ctypes import c_char_p, c_long, c_uint, c_int
 from datetime import date
-from notmuch.globals import (nmlib, STATUS, NotmuchError, Enum, _str,
+from notmuch.globals import (
+nmlib, STATUS, NotmuchError, Enum, _str, Python3StringMixIn,
 NotmuchTagsP, NotmuchMessagesP, NotmuchMessageP, NotmuchFilenamesP)
 from notmuch.tag import Tags
 from notmuch.filename import Filenames
@@ -239,7 +240,7 @@ class Messages(object):
 sys.stdout.write(set_end)
 
 
-class Message(object):
+class Message(Python3StringMixIn):
 Represents a single Email message
 
 Technically, this wraps the underlying *notmuch_message_t*
@@ -796,9 +797,6 @@ class Message(object):
 Represent a Message() object by str()
 return self.__str__()
 
-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 format = %s (%s) (%s)
 return format % (self.get_header('from'),
diff --git a/bindings/python/notmuch/tag.py b/bindings/python/notmuch/tag.py
index d42ba77..ceb7244 100644
--- a/bindings/python/notmuch/tag.py
+++ b/bindings/python/notmuch/tag.py
@@ -17,10 +17,10 @@ along with notmuch.  If not, see 
http://www.gnu.org/licenses/.
 Copyright 2010 Sebastian Spaeth sebast...@sspaeth.de'
 
 from ctypes import c_char_p
-from notmuch.globals import nmlib, STATUS, NotmuchError, NotmuchTagsP
+from notmuch.globals import nmlib, STATUS, NotmuchError, NotmuchTagsP, _str, 
Python3StringMixIn
 
 
-class Tags(object):
+class Tags(Python3StringMixIn):
 Represents a list of notmuch tags
 
 This object provides an iterator over a list of notmuch tags (which
@@ -111,9 +111,6 @@ class Tags(object):
 left.
 return self._valid(self._tags)  0
 
-def __str__(self):
-return unicode(self).encode('utf-8')
-
 def __unicode__(self):
 string representation of :class:`Tags`: a space separated list of 
tags
 
diff --git a/bindings/python/notmuch/thread.py 
b/bindings/python/notmuch/thread.py
index 39285d6..7393097 100644
--- a/bindings/python/notmuch/thread.py
+++ 

Re: [afew] announcing afew, an universal tagging solution with some fancy features

2011-12-14 Thread Jani Nikula
On Wed, 14 Dec 2011 11:42:36 +0100, Justus Winter 
4win...@informatik.uni-hamburg.de wrote:
 https://github.com/teythoon/afew
 
 It has some nifty features, citing the README:


Basic tagging stuff requires no configuration, just run

$ afew --tag --new

To do this automatically you can add the following hook into your
~/.offlineimaprc:

postsynchook = ionice -c 3 chrt --idle 0 /bin/sh -c notmuch new  afew
--tag --new


FYI, notmuch new now supports hooks you can use for this. Currently
only in the git repo, though.

BR,
Jani.
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [afew] announcing afew, an universal tagging solution with some fancy features

2011-12-14 Thread Patrick Totzke
Hi Justus,

I have just tried your script and have some questions/remarks about it:

* mkdir -p ~/.config/afew ~/.local/share/afew/categories
  As far as I can see, this is not needed if one doesn't use ClassifyingFilter,
  so its OK not to do this directly from the setup.py somehow.
  But it would be nice if a first run uf `afew --learn` would
  create these (or die gracefully instead of raising the 
afew.DBACL.BackendError).

* if you renamed the README  co to include the suffix .md github would nicely
  render them on the project page.

* I need some more info on how the config works: first, the order in which the
  sections are defined specifies the filter-pipeline yes?
  Secondly, what exactly is a filter object in the config?
  Specifically, what do these 3 lines do:
  https://github.com/teythoon/afew/blob/master/docs/tag_filters#L39

* this is surely a user error: I cannot use afew for initial tagging as 
expected:
  I installed as stated in the README,
  trained some of my existing tags and called `afew --update-reference` and 
`afew --update`.
  The test with `afew --classify -- ..` works nicely.
  Now I tagges all my mails with is:new, and called `afew --tag --new`.
  This returns immediately without output and all my messages are still tagged 
new.
  Also, -vv does not result in any output..
  ideas?

Looking forward to replacing my sort script with this.
Thanks,
/p



___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


ANNOUNCE: nottoomuch-addresses.pl version 1.4

2011-12-14 Thread Tomi Ollila

notmuch-addresses.sh -- email address substring matcher -- completion
helper version 1.4 is available.

This version uses 'notmuch search --sort=newest-first --output=files ...'
(instead of notmuch show ...) to retrieve message information from notmuch
... and now scans headers from mail files itself.

* This is now somewhat faster as the whole emails are not read.
* The sort order is better guaranteed.
* Current memory consumption of 'notmuch show --format=text' does not
  hit users.

Addresses file header format is same as in 1.3 so upgrading from that
version does not cause addresses file rebuild.

Location: http://www.iki.fi/too/nottoomuch/nottoomuch-addresses.sh

Sha1sum: 871f481a229a6e3295c02fa80270a7a318d226c

Web page: http://www.iki.fi/too/nottoomuch/nottoomuch-addresses/


Note to upgraders: this version may not find as many addreses as older
ones -- those also scanned From:, To: and Cc: in message bodies. 
Current version seldom leaks to the body of the message...
So, don't get alarmed if --update --rebuild finds less addresses.


Enjoy!
Tomi
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[Alpha Patch 2/2] test: update dump-restore tests for 8 bit characters.

2011-12-14 Thread David Bremner
From: David Bremner brem...@debian.org

hex-escape: fix for handling of 8 bit chars

The low level problem was passing negative numbers to sprintf(s,%x);
we fix this and clarify the api for hex_(decode|encode) by making
encode go from (unsigned char *) (i.e. 8bit) to (char *) and decode
vise-versa.
---
 test/dump-restore |2 --
 test/hex-escaping |1 -
 util/hex-escape.c |   26 +++---
 util/hex-escape.h |6 --
 4 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/test/dump-restore b/test/dump-restore
index eee1773..c5b2e86 100755
--- a/test/dump-restore
+++ b/test/dump-restore
@@ -114,7 +114,6 @@ notmuch dump --format=notmuch  BACKUP
 notmuch tag +$tag1 +$tag2 +$tag3 -inbox -unread *
 
 test_begin_subtest 'format=notmuch, round trip with strange tags'
-   test_subtest_known_broken
notmuch dump --format=notmuch  EXPECTED.$test_count
notmuch dump --format=notmuch | notmuch restore --format=notmuch
notmuch dump --format=notmuch  OUTPUT.$test_count
@@ -122,7 +121,6 @@ test_expect_equal_file EXPECTED.$test_count 
OUTPUT.$test_count
 
 
 test_begin_subtest 'format=notmuch, checking encoded output'
-test_subtest_known_broken
 cp /dev/null EXPECTED.$test_count
 notmuch dump --format=notmuch -- from:cworth |\
 awk { print \$1 \ $enc1 $enc2 $enc3\ }  EXPECTED.$test_count
diff --git a/test/hex-escaping b/test/hex-escaping
index 2053fb0..daa6446 100755
--- a/test/hex-escaping
+++ b/test/hex-escaping
@@ -19,7 +19,6 @@ $TEST_DIRECTORY/hex-xcode e   EXPECTED.$test_count |\
 test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
 
 test_begin_subtest round trip 8bit chars
-test_subtest_known_broken
 echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a'  EXPECTED.$test_count
 $TEST_DIRECTORY/hex-xcode d   EXPECTED.$test_count |\
$TEST_DIRECTORY/hex-xcode e  OUTPUT.$test_count
diff --git a/util/hex-escape.c b/util/hex-escape.c
index dcf87cf..565ae99 100644
--- a/util/hex-escape.c
+++ b/util/hex-escape.c
@@ -28,23 +28,24 @@ static const size_t default_buf_size=1024;
 static const char* output_charset=
 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-_@=.:,;
 
-static const char escape_char='%';
+static const int escape_char = '%';
 
 static int
 is_output (char c) {
 return (strchr (output_charset, c) != NULL);
 }
 
+typedef unsigned char _octet;
 
 static int
-maybe_realloc(void *ctx, size_t needed, char **out, size_t *out_size)
+maybe_realloc(void *ctx, size_t needed, _octet **out, size_t *out_size)
 {
 if (*out_size  needed) {
 
if (*out == NULL)
*out = talloc_size(ctx,needed);
else
-   *out = talloc_realloc(ctx,*out,char,needed);
+   *out = talloc_realloc(ctx, *out, _octet, needed);
 
if (*out == NULL)
return 0;
@@ -56,24 +57,27 @@ maybe_realloc(void *ctx, size_t needed, char **out, size_t 
*out_size)
 
 
 hex_status_t
-hex_encode (void *ctx, const char *in, char **out, size_t *out_size)
+hex_encode (void *ctx, const _octet *in, char **out, size_t *out_size)
 {
 
-const char *p;
+const _octet *p;
 char *q;
 
-int escape_count=0;
+size_t escape_count = 0;
+size_t len = 0;
 size_t needed;
 
-for  (p = in; *p; p++)
+for  (p = in; *p; p++) {
escape_count += (! is_output (*p));
+   len++;
+}
 
-needed = strlen (in) + 2*escape_count + 1;
+needed = len + 2*escape_count + 1;
 
 if (*out == NULL)
*out_size=0;
 
-if (!maybe_realloc (ctx, needed, out, out_size))
+if (!maybe_realloc (ctx, needed, (_octet**)out, out_size))
return HEX_OUT_OF_MEMORY;
 
 q = *out;
@@ -94,12 +98,12 @@ hex_encode (void *ctx, const char *in, char **out, size_t 
*out_size)
 
 
 hex_status_t
-hex_decode (void *ctx, const char *in, char **out, size_t *out_size) {
+hex_decode (void *ctx, const char *in, _octet **out, size_t *out_size) {
 
 char buf[3];
 
 const char *p;
-char *q;
+_octet *q;
 
 size_t escape_count = 0;
 size_t needed = 0;
diff --git a/util/hex-escape.h b/util/hex-escape.h
index 98ecbe0..e04aff5 100644
--- a/util/hex-escape.h
+++ b/util/hex-escape.h
@@ -8,8 +8,10 @@ typedef enum hex_status {
 } hex_status_t;
 
 hex_status_t
-hex_encode (void *talloc_ctx, const char *in, char **out, size_t *out_size);
+hex_encode (void *talloc_ctx, const unsigned char *in, char **out,
+   size_t *out_size);
 
 hex_status_t
-hex_decode (void *talloc_ctx, const char *in, char **out, size_t *out_size);
+hex_decode (void *talloc_ctx, const char *in, unsigned char **out,
+   size_t *out_size);
 #endif
-- 
1.7.7.3

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[Alpha Patch 1/2] test: add (currently broken) test 8 bit characters hex-escape and dump-restore

2011-12-14 Thread David Bremner
From: David Bremner brem...@debian.org

The problem is a use of signed chars in places where unsigned
chars (i.e. 0-255) should be used.
---

Well, I did mention more tests were needed ;). I failed to test 8 bit
(127) stuff and sure enough it was broken.  This sets up some tests
to demonstrate the problem and the next patch fixes it.

 test/dump-restore |9 +++--
 test/hex-escaping |7 +++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/test/dump-restore b/test/dump-restore
index 122de5c..eee1773 100755
--- a/test/dump-restore
+++ b/test/dump-restore
@@ -106,11 +106,15 @@ enc1=$($TEST_DIRECTORY/hex-xcode e $tag1)
 tag2=$(printf 'this\n tag\t has\n spaces')
 enc2=$($TEST_DIRECTORY/hex-xcode e $tag2)
 
+enc3='%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a'
+tag3=$($TEST_DIRECTORY/hex-xcode d $enc3)
+
 notmuch dump --format=notmuch  BACKUP
 
-notmuch tag +$tag1 +$tag2 -inbox -unread *
+notmuch tag +$tag1 +$tag2 +$tag3 -inbox -unread *
 
 test_begin_subtest 'format=notmuch, round trip with strange tags'
+   test_subtest_known_broken
notmuch dump --format=notmuch  EXPECTED.$test_count
notmuch dump --format=notmuch | notmuch restore --format=notmuch
notmuch dump --format=notmuch  OUTPUT.$test_count
@@ -118,9 +122,10 @@ test_expect_equal_file EXPECTED.$test_count 
OUTPUT.$test_count
 
 
 test_begin_subtest 'format=notmuch, checking encoded output'
+test_subtest_known_broken
 cp /dev/null EXPECTED.$test_count
 notmuch dump --format=notmuch -- from:cworth |\
-awk { print \$1 \ $enc1 $enc2\ }  EXPECTED.$test_count
+awk { print \$1 \ $enc1 $enc2 $enc3\ }  EXPECTED.$test_count
 
 notmuch dump --format=notmuch -- from:cworth   OUTPUT.$test_count
 test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
diff --git a/test/hex-escaping b/test/hex-escaping
index d0a993e..2053fb0 100755
--- a/test/hex-escaping
+++ b/test/hex-escaping
@@ -17,4 +17,11 @@ printf 'this\n tag\t has\n spaces\n'  EXPECTED.$test_count
 $TEST_DIRECTORY/hex-xcode e   EXPECTED.$test_count |\
$TEST_DIRECTORY/hex-xcode d  OUTPUT.$test_count
 test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest round trip 8bit chars
+test_subtest_known_broken
+echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a'  EXPECTED.$test_count
+$TEST_DIRECTORY/hex-xcode d   EXPECTED.$test_count |\
+   $TEST_DIRECTORY/hex-xcode e  OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
 test_done
-- 
1.7.7.3

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [Alpha PATCH 6/6] test: second set of dump/restore --format=notmuch tests

2011-12-14 Thread Dmitry Kurochkin
On Tue, 13 Dec 2011 16:27:55 -0400, David Bremner da...@tethera.net wrote:
 From: David Bremner brem...@debian.org
 
 These one need the completed functionality in notmuch-restore. Fairly
 exotic tags are tested, but no weird message id's.
 ---
  test/dump-restore |   33 +
  1 files changed, 33 insertions(+), 0 deletions(-)
 
 diff --git a/test/dump-restore b/test/dump-restore
 index 48caf4e..122de5c 100755
 --- a/test/dump-restore
 +++ b/test/dump-restore
 @@ -94,4 +94,37 @@ notmuch dump --format=sup -- from:cworth | tr -d \(\)  
 EXPECTED.$test_count
  notmuch dump --format=notmuch -- from:cworth  OUTPUT.$test_count
  test_expect_equal_file OUTPUT.$test_count EXPECTED.$test_count
  
 +test_begin_subtest format=notmuch, # round-trip
 +notmuch dump --format=sup | sort  EXPECTED.$test_count
 +notmuch dump --format=notmuch | notmuch restore --format=notmuch
 +notmuch dump --format=sup | sort  OUTPUT.$test_count
 +test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
 +
 +tag1='comic_swear=$^%$^%\\//-+$^%$'
 +enc1=$($TEST_DIRECTORY/hex-xcode e $tag1)
 +
 +tag2=$(printf 'this\n tag\t has\n spaces')
 +enc2=$($TEST_DIRECTORY/hex-xcode e $tag2)
 +
 +notmuch dump --format=notmuch  BACKUP
 +
 +notmuch tag +$tag1 +$tag2 -inbox -unread *
 +
 +test_begin_subtest 'format=notmuch, round trip with strange tags'
 +   notmuch dump --format=notmuch  EXPECTED.$test_count
 +   notmuch dump --format=notmuch | notmuch restore --format=notmuch
 +   notmuch dump --format=notmuch  OUTPUT.$test_count

Noticed this while looking at the 8bit patch.  The indent offset should
be 4.

Regards,
  Dmitry

 +test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
 +
 +
 +test_begin_subtest 'format=notmuch, checking encoded output'
 +cp /dev/null EXPECTED.$test_count
 +notmuch dump --format=notmuch -- from:cworth |\
 +  awk { print \$1 \ $enc1 $enc2\ }  EXPECTED.$test_count
 +
 +notmuch dump --format=notmuch -- from:cworth   OUTPUT.$test_count
 +test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
 +
 +notmuch restore --format=notmuch  BACKUP
 +
  test_done
 -- 
 1.7.5.4
 
 ___
 notmuch mailing list
 notmuch@notmuchmail.org
 http://notmuchmail.org/mailman/listinfo/notmuch
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [Alpha Patch 2/2] test: update dump-restore tests for 8 bit characters.

2011-12-14 Thread Dmitry Kurochkin
On Wed, 14 Dec 2011 16:14:01 -0400, David Bremner da...@tethera.net wrote:
 From: David Bremner brem...@debian.org
 
 hex-escape: fix for handling of 8 bit chars
 
 The low level problem was passing negative numbers to sprintf(s,%x);
 we fix this and clarify the api for hex_(decode|encode) by making
 encode go from (unsigned char *) (i.e. 8bit) to (char *) and decode
 vise-versa.

I did not do a proper review.  But I think the encoder and decoder
should accept and return the same type, either char* or unsigned char*.
The decision should be based on what type strings (that would be fed to
the encoder and decoder) have in notmuch code.  I guess it is char*, so
the encoder and decoder should take and return char*.  Internally we
would cast char* to unsigned char*.

Also, I do not like the _octet typedef in hex-escape.c.  Having
different function parameters in header and .c is confusing.  IMO we
should either move the typedef to some header, or just use unsigned
char.

Regards,
  Dmitry

 ---
  test/dump-restore |2 --
  test/hex-escaping |1 -
  util/hex-escape.c |   26 +++---
  util/hex-escape.h |6 --
  4 files changed, 19 insertions(+), 16 deletions(-)
 
 diff --git a/test/dump-restore b/test/dump-restore
 index eee1773..c5b2e86 100755
 --- a/test/dump-restore
 +++ b/test/dump-restore
 @@ -114,7 +114,6 @@ notmuch dump --format=notmuch  BACKUP
  notmuch tag +$tag1 +$tag2 +$tag3 -inbox -unread *
  
  test_begin_subtest 'format=notmuch, round trip with strange tags'
 -   test_subtest_known_broken
 notmuch dump --format=notmuch  EXPECTED.$test_count
 notmuch dump --format=notmuch | notmuch restore --format=notmuch
 notmuch dump --format=notmuch  OUTPUT.$test_count
 @@ -122,7 +121,6 @@ test_expect_equal_file EXPECTED.$test_count 
 OUTPUT.$test_count
  
  
  test_begin_subtest 'format=notmuch, checking encoded output'
 -test_subtest_known_broken
  cp /dev/null EXPECTED.$test_count
  notmuch dump --format=notmuch -- from:cworth |\
awk { print \$1 \ $enc1 $enc2 $enc3\ }  EXPECTED.$test_count
 diff --git a/test/hex-escaping b/test/hex-escaping
 index 2053fb0..daa6446 100755
 --- a/test/hex-escaping
 +++ b/test/hex-escaping
 @@ -19,7 +19,6 @@ $TEST_DIRECTORY/hex-xcode e   EXPECTED.$test_count |\
  test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
  
  test_begin_subtest round trip 8bit chars
 -test_subtest_known_broken
  echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a'  
 EXPECTED.$test_count
  $TEST_DIRECTORY/hex-xcode d   EXPECTED.$test_count |\
   $TEST_DIRECTORY/hex-xcode e  OUTPUT.$test_count
 diff --git a/util/hex-escape.c b/util/hex-escape.c
 index dcf87cf..565ae99 100644
 --- a/util/hex-escape.c
 +++ b/util/hex-escape.c
 @@ -28,23 +28,24 @@ static const size_t default_buf_size=1024;
  static const char* output_charset=
  ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-_@=.:,;
  
 -static const char escape_char='%';
 +static const int escape_char = '%';
  
  static int
  is_output (char c) {
  return (strchr (output_charset, c) != NULL);
  }
  
 +typedef unsigned char _octet;
  
  static int
 -maybe_realloc(void *ctx, size_t needed, char **out, size_t *out_size)
 +maybe_realloc(void *ctx, size_t needed, _octet **out, size_t *out_size)
  {
  if (*out_size  needed) {
  
   if (*out == NULL)
   *out = talloc_size(ctx,needed);
   else
 - *out = talloc_realloc(ctx,*out,char,needed);
 + *out = talloc_realloc(ctx, *out, _octet, needed);
  
   if (*out == NULL)
   return 0;
 @@ -56,24 +57,27 @@ maybe_realloc(void *ctx, size_t needed, char **out, 
 size_t *out_size)
  
  
  hex_status_t
 -hex_encode (void *ctx, const char *in, char **out, size_t *out_size)
 +hex_encode (void *ctx, const _octet *in, char **out, size_t *out_size)
  {
  
 -const char *p;
 +const _octet *p;
  char *q;
  
 -int escape_count=0;
 +size_t escape_count = 0;
 +size_t len = 0;
  size_t needed;
  
 -for  (p = in; *p; p++)
 +for  (p = in; *p; p++) {
   escape_count += (! is_output (*p));
 + len++;
 +}
  
 -needed = strlen (in) + 2*escape_count + 1;
 +needed = len + 2*escape_count + 1;
  
  if (*out == NULL)
   *out_size=0;
  
 -if (!maybe_realloc (ctx, needed, out, out_size))
 +if (!maybe_realloc (ctx, needed, (_octet**)out, out_size))
   return HEX_OUT_OF_MEMORY;
  
  q = *out;
 @@ -94,12 +98,12 @@ hex_encode (void *ctx, const char *in, char **out, size_t 
 *out_size)
  
  
  hex_status_t
 -hex_decode (void *ctx, const char *in, char **out, size_t *out_size) {
 +hex_decode (void *ctx, const char *in, _octet **out, size_t *out_size) {
  
  char buf[3];
  
  const char *p;
 -char *q;
 +_octet *q;
  
  size_t escape_count = 0;
  size_t needed = 0;
 diff --git a/util/hex-escape.h b/util/hex-escape.h
 index 98ecbe0..e04aff5 100644
 --- a/util/hex-escape.h
 +++ b/util/hex-escape.h
 @@ -8,8 

Re: [PATCH 2/5] lib: Add a MTIME value to every mail document

2011-12-14 Thread Mark Anderson
On Tue, 13 Dec 2011 11:11:42 -0600, Thomas Jost schno...@schnouki.net wrote:
 This is a time_t value, similar to the message date (TIMESTAMP). It is first 
 set
 when the message is added to the database, and is then updated every time a 
 tag
 is added or removed. It can thus be used for doing incremental dumps of the
 database or for synchronizing it between several computers.
 
 This value can be read freely (with notmuch_message_get_mtime()) but for now 
 it
 can't be set to an arbitrary value: it can only be set to now when updated.
 There's no specific reason for this except that I don't really see a real use
 case for setting it to an arbitrary value.

I think it would be easier to write some testcases if the last modified
time could be touched directly.  Perhaps they aren't in the set of must
have, but it's what comes to mind.

-Mark

 ---
  lib/database.cc   |7 ++-
  lib/message.cc|   32 
  lib/notmuch-private.h |6 +-
  lib/notmuch.h |4 
  4 files changed, 47 insertions(+), 2 deletions(-)
 
 diff --git a/lib/database.cc b/lib/database.cc
 index 2025189..6dc6f73 100644
 --- a/lib/database.cc
 +++ b/lib/database.cc
 @@ -81,7 +81,7 @@ typedef struct {
   *   STRING is the name of a file within that
   *   directory for this mail message.
   *
 - *A mail document also has four values:
 + *A mail document also has five values:
   *
   *   TIMESTAMP:  The time_t value corresponding to the message's
   *   Date header.
 @@ -92,6 +92,9 @@ typedef struct {
   *
   *   SUBJECT:The value of the Subject header
   *
 + *   MTIME:  The time_t value corresponding to the last time
 + *   a tag was added or removed on the message.
 + *
   * In addition, terms from the content of the message are added with
   * from, to, attachment, and subject prefixes for use by the
   * user in searching. Similarly, terms from the path of the mail
 @@ -1735,6 +1738,8 @@ notmuch_database_add_message (notmuch_database_t 
 *notmuch,
   date = notmuch_message_file_get_header (message_file, date);
   _notmuch_message_set_header_values (message, date, from, subject);
  
 +_notmuch_message_update_mtime (message);
 +
   _notmuch_message_index_file (message, filename);
   } else {
   ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;
 diff --git a/lib/message.cc b/lib/message.cc
 index 0075425..0c98589 100644
 --- a/lib/message.cc
 +++ b/lib/message.cc
 @@ -830,6 +830,34 @@ _notmuch_message_set_header_values (notmuch_message_t 
 *message,
  message-doc.add_value (NOTMUCH_VALUE_SUBJECT, subject);
  }
  
 +/* Get the message mtime, i.e. when it was added or the last time a tag was
 + * added/removed. */
 +time_t
 +notmuch_message_get_mtime (notmuch_message_t *message)
 +{
 +std::string value;
 +
 +try {
 + value = message-doc.get_value (NOTMUCH_VALUE_MTIME);
 +} catch (Xapian::Error error) {
 + INTERNAL_ERROR (Failed to read mtime value from document.);
 + return 0;
 +}
 +
 +return Xapian::sortable_unserialise (value);
 +}
 +
 +/* Set the message mtime to now. */
 +void
 +_notmuch_message_update_mtime (notmuch_message_t *message)
 +{
 +time_t time_value;
 +
 +time_value = time (NULL);
 +message-doc.add_value (NOTMUCH_VALUE_MTIME,
 +Xapian::sortable_serialise (time_value));
 +}
 +
  /* Synchronize changes made to message-doc out into the database. */
  void
  _notmuch_message_sync (notmuch_message_t *message)
 @@ -994,6 +1022,8 @@ notmuch_message_add_tag (notmuch_message_t *message, 
 const char *tag)
   private_status);
  }
  
 +_notmuch_message_update_mtime (message);
 +
  if (! message-frozen)
   _notmuch_message_sync (message);
  
 @@ -1022,6 +1052,8 @@ notmuch_message_remove_tag (notmuch_message_t *message, 
 const char *tag)
   private_status);
  }
  
 +_notmuch_message_update_mtime (message);
 +
  if (! message-frozen)
   _notmuch_message_sync (message);
  
 diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
 index 60a932f..9859872 100644
 --- a/lib/notmuch-private.h
 +++ b/lib/notmuch-private.h
 @@ -95,7 +95,8 @@ typedef enum {
  NOTMUCH_VALUE_TIMESTAMP = 0,
  NOTMUCH_VALUE_MESSAGE_ID,
  NOTMUCH_VALUE_FROM,
 -NOTMUCH_VALUE_SUBJECT
 +NOTMUCH_VALUE_SUBJECT,
 +NOTMUCH_VALUE_MTIME
  } notmuch_value_t;
  
  /* Xapian (with flint backend) complains if we provide a term longer
 @@ -276,6 +277,9 @@ _notmuch_message_set_header_values (notmuch_message_t 
 *message,
   const char *from,
   const char *subject);
  void
 +_notmuch_message_update_mtime (notmuch_message_t *message);
 +
 +void
  _notmuch_message_sync (notmuch_message_t *message);
  
  notmuch_status_t
 diff --git a/lib/notmuch.h 

[alot] on Arch Linux

2011-12-14 Thread Philipp Überbacher

Hi there,
I'm a new notmuch/alot user, this is my first mail since I switched from
sup. Yes, switched. notmuch/alot works for me well enough now to be
usable.

I run Arch Linux. Here's some information for fellow Archers:
PKGBUILD for alot-git: https://aur.archlinux.org/packages.php?ID=54955
Should work just fine. If you want to help debug alot, change
_gitname=master to the name of the branch, build and install as usual.

You should currently avoid the alot PKGBUILD from AUR, it also points to
git and has some other mistakes. I'll see to it that it gets deleted and
maybe put a PKGBUILD with the release-version into its place.

Another little trap:
Arch doesn't supply a mailcap file, alot needs it for all those funky
html mails. As a solution until alot handles those mails better:
create ~/.mailcap
put the following line into it:
text/html; /usr/bin/lynx -dump '%s'; copiousoutput; description=HTML
Text; nametemplate=%s.html

Hope that helps,
thanks Patrick for writing alot, fixing bugs and helping with the
config.

Regards,
Philipp


___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [Alpha Patch 2/2] test: update dump-restore tests for 8 bit characters.

2011-12-14 Thread David Bremner
On Thu, 15 Dec 2011 00:36:38 +0400, Dmitry Kurochkin 
dmitry.kuroch...@gmail.com wrote:
 
 I did not do a proper review.  But I think the encoder and decoder
 should accept and return the same type, either char* or unsigned char*.
 The decision should be based on what type strings (that would be fed to
 the encoder and decoder) have in notmuch code.  I guess it is char*, so
 the encoder and decoder should take and return char*.  Internally we
 would cast char* to unsigned char*.

After staring at the draft C99 standard a bit, I'm inclined to agree. I
think char is the generic, which to my horror is really either unsigned
char or signed char is an implementation dependent way.

The info I was missing was in the description of string.h

,
| 3 For all functions in this subclause, each character shall be interpreted as 
if it had the type
|  unsigned char (and therefore every possible object representation is valid 
and has a
| different value).
`

I'll fix this in git, but I probably won't bother with another round of
patches yet.
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 2/5] lib: Add a MTIME value to every mail document

2011-12-14 Thread Austin Clements
A few minor comments below.

At a higher level, I'm curious what the tag synchronization protocol
you're building on top of this is.  I can't think of one that doesn't
have race conditions, but maybe I'm not thinking about it right.

Quoth Thomas Jost on Dec 13 at  6:11 pm:
 This is a time_t value, similar to the message date (TIMESTAMP). It is first 
 set
 when the message is added to the database, and is then updated every time a 
 tag
 is added or removed. It can thus be used for doing incremental dumps of the
 database or for synchronizing it between several computers.
 
 This value can be read freely (with notmuch_message_get_mtime()) but for now 
 it
 can't be set to an arbitrary value: it can only be set to now when updated.
 There's no specific reason for this except that I don't really see a real use
 case for setting it to an arbitrary value.
 ---
  lib/database.cc   |7 ++-
  lib/message.cc|   32 
  lib/notmuch-private.h |6 +-
  lib/notmuch.h |4 
  4 files changed, 47 insertions(+), 2 deletions(-)
 
 diff --git a/lib/database.cc b/lib/database.cc
 index 2025189..6dc6f73 100644
 --- a/lib/database.cc
 +++ b/lib/database.cc
 @@ -81,7 +81,7 @@ typedef struct {
   *   STRING is the name of a file within that
   *   directory for this mail message.
   *
 - *A mail document also has four values:
 + *A mail document also has five values:
   *
   *   TIMESTAMP:  The time_t value corresponding to the message's
   *   Date header.
 @@ -92,6 +92,9 @@ typedef struct {
   *
   *   SUBJECT:The value of the Subject header
   *
 + *   MTIME:  The time_t value corresponding to the last time
 + *   a tag was added or removed on the message.
 + *
   * In addition, terms from the content of the message are added with
   * from, to, attachment, and subject prefixes for use by the
   * user in searching. Similarly, terms from the path of the mail
 @@ -1735,6 +1738,8 @@ notmuch_database_add_message (notmuch_database_t 
 *notmuch,
   date = notmuch_message_file_get_header (message_file, date);
   _notmuch_message_set_header_values (message, date, from, subject);
  
 +_notmuch_message_update_mtime (message);

Indentation.

 +
   _notmuch_message_index_file (message, filename);
   } else {
   ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;
 diff --git a/lib/message.cc b/lib/message.cc
 index 0075425..0c98589 100644
 --- a/lib/message.cc
 +++ b/lib/message.cc
 @@ -830,6 +830,34 @@ _notmuch_message_set_header_values (notmuch_message_t 
 *message,
  message-doc.add_value (NOTMUCH_VALUE_SUBJECT, subject);
  }
  
 +/* Get the message mtime, i.e. when it was added or the last time a tag was
 + * added/removed. */
 +time_t
 +notmuch_message_get_mtime (notmuch_message_t *message)
 +{
 +std::string value;
 +
 +try {
 + value = message-doc.get_value (NOTMUCH_VALUE_MTIME);
 +} catch (Xapian::Error error) {
 + INTERNAL_ERROR (Failed to read mtime value from document.);
 + return 0;
 +}

For compatibility, this should handle the case when
NOTMUCH_VALUE_MTIME is missing, probably by just returning 0.  As it
is, value will be an empty string and sortable_unserialise is
undefined on strings that weren't produced by sortable_serialise.

 +
 +return Xapian::sortable_unserialise (value);
 +}
 +
 +/* Set the message mtime to now. */
 +void
 +_notmuch_message_update_mtime (notmuch_message_t *message)
 +{
 +time_t time_value;
 +
 +time_value = time (NULL);
 +message-doc.add_value (NOTMUCH_VALUE_MTIME,
 +Xapian::sortable_serialise (time_value));

Indentation.

 +}
 +
  /* Synchronize changes made to message-doc out into the database. */
  void
  _notmuch_message_sync (notmuch_message_t *message)
 @@ -994,6 +1022,8 @@ notmuch_message_add_tag (notmuch_message_t *message, 
 const char *tag)
   private_status);
  }
  
 +_notmuch_message_update_mtime (message);
 +
  if (! message-frozen)
   _notmuch_message_sync (message);
  
 @@ -1022,6 +1052,8 @@ notmuch_message_remove_tag (notmuch_message_t *message, 
 const char *tag)
   private_status);
  }
  
 +_notmuch_message_update_mtime (message);
 +
  if (! message-frozen)
   _notmuch_message_sync (message);
  
 diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
 index 60a932f..9859872 100644
 --- a/lib/notmuch-private.h
 +++ b/lib/notmuch-private.h
 @@ -95,7 +95,8 @@ typedef enum {
  NOTMUCH_VALUE_TIMESTAMP = 0,
  NOTMUCH_VALUE_MESSAGE_ID,
  NOTMUCH_VALUE_FROM,
 -NOTMUCH_VALUE_SUBJECT
 +NOTMUCH_VALUE_SUBJECT,
 +NOTMUCH_VALUE_MTIME
  } notmuch_value_t;
  
  /* Xapian (with flint backend) complains if we provide a term longer
 @@ -276,6 +277,9 @@ _notmuch_message_set_header_values (notmuch_message_t 
 *message,
   

Re: [PATCH] debian: add upstream-tag and fix debian-tag configs for git-buildpackage

2011-12-14 Thread David Bremner
On Sun, 11 Dec 2011 17:21:09 -0800, Jameson Graef Rollins 
jroll...@finestructure.net wrote:
 Debian tags have been using '/', instead of '-' as a separator.

pushed

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v3] emacs: support notmuch new as a notmuch-poll-script

2011-12-14 Thread David Bremner
On Mon, 12 Dec 2011 22:50:04 +0200, Jani Nikula j...@nikula.org wrote:
 Support nil value for notmuch-poll-script to run notmuch new instead of
 an external script, and make this the new default. notmuch new is run
 using the configured notmuch-command.

pushed.

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch