9 years agoMerge remote-tracking branch 'wberrier/master' master
W. Trevor King [Thu, 7 Feb 2013 15:58:25 +0000 (10:58 -0500)]
Merge remote-tracking branch 'wberrier/master'

* wberrier/master:
  Support older versions of pyxdg
  Demote log message when xdg is missing from error to warning
  Remove TODO item for cache expiration

9 years agoSupport older versions of pyxdg
Wade Berrier [Sat, 26 Jan 2013 03:43:10 +0000 (20:43 -0700)]
Support older versions of pyxdg

save_cache_path was added in 0.21

Fall back to ~/.cache and make sure the directory exists
(that's what save_cache_path does)

9 years agoDemote log message when xdg is missing from error to warning
Wade Berrier [Sat, 26 Jan 2013 03:41:51 +0000 (20:41 -0700)]
Demote log message when xdg is missing from error to warning

Otherwise the log messages clutter up the mutt screen

9 years agoRemove TODO item for cache expiration
Wade Berrier [Sat, 26 Jan 2013 03:45:17 +0000 (20:45 -0700)]
Remove TODO item for cache expiration

9 years Follow the the XDG Base Directory Specification
W. Trevor King [Thu, 24 Jan 2013 23:18:33 +0000 (18:18 -0500)] Follow the the XDG Base Directory Specification

Standards are good, especially standards for keeping a plethora of
config and data files files organized.  Use PyXDG (an optional new
dependency) to handle all of the specification logic.

The default config file is now ~/.config/mutt-ldap.cfg and the default
cache file is now ~/.cache/mutt-ldap.json.  The contents of these
files has not changed.  Without the PyXDG dependency, these defaults
are hard-coded.  With the PyXDG dependency, the defaults shift
depending on $XDG_CONFIG_HOME, $XDG_CACHE_HOME, etc.

9 years agoREADME: Fix 'contaning' -> 'containing' typo in Usage
W. Trevor King [Thu, 24 Jan 2013 23:04:22 +0000 (18:04 -0500)]
README: Fix 'contaning' -> 'containing' typo in Usage

9 years Factor configuration out into a Config class
W. Trevor King [Thu, 24 Jan 2013 22:46:19 +0000 (17:46 -0500)] Factor configuration out into a Config class

This pulls a bunch of dynamic default calculation hackish encoding
manipulation out of the __name__ == '__main__' block, which makes it
easier to read.

9 years Also wrap stderr in a codecs writer
W. Trevor King [Thu, 24 Jan 2013 22:26:40 +0000 (17:26 -0500)] Also wrap stderr in a codecs writer

So Unicode log messages handled by StreamHandler will be properly
encoded.  In Python 2.7.3 (and probably other 2.x versions),
StreamHandler.emit() falls back on UTF-8 if stream.encoding is None.
With this change, it will use the configured output encoding instead
of guessing.

9 years Use LOG.error() instead of sys.stderr.write()
W. Trevor King [Thu, 24 Jan 2013 22:25:47 +0000 (17:25 -0500)] Use LOG.error() instead of sys.stderr.write()

9 years Don't load the config file if were being imported as a library
W. Trevor King [Thu, 24 Jan 2013 22:24:49 +0000 (17:24 -0500)] Don't load the config file if were being imported as a library

9 years Rename sys to _sys on import
W. Trevor King [Thu, 24 Jan 2013 22:18:58 +0000 (17:18 -0500)] Rename sys to _sys on import

Keeping the namespace clean when __name__ == '__main__' is not really
important, but this way all the imports are consistently renamed.
This future-proofs the code in case those modules ever need to get
shifted to module-wide imports.

9 years Add an output-encoding option v0.1
W. Trevor King [Thu, 24 Jan 2013 19:01:52 +0000 (14:01 -0500)] Add an output-encoding option

This avoids crashing with:

  UnicodeEncodeError: 'ascii' codec can't encode characters

when's stdout is not connected to a terminal (and
therefore doesn't have sys.stdout.encodign set up).

  $ python2.7 -c "print(u'α')" | cat
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
  UnicodeEncodeError: 'ascii' codec can't encode characters in
    position 0-1: ordinal not in range(128)
  $ python2.7 -c 'import sys; print(sys.stdout.encoding)'
  $ python2.7 -c 'import sys; print(sys.stdout.encoding)' | cat
  $ python3.2 -c "print('α')" | cat
  $ python3.2 -c 'import sys; print(sys.stdout.encoding)'
  $ python3.2 -c 'import sys; print(sys.stdout.encoding)' | cat

Both settings should match the value of the Mutt configuration
variable $charset [1,2]:

On Thu, Jan 24, 2013 at 06:25:24PM +0000, Michael Elkins wrote:
> On Thu, Jan 24, 2013 at 12:36:02PM -0500, W. Trevor King wrote:
> > I have a script that queries for address completion using the
> > query_command setting, but the docs are silent on the encoding for
> > the arguments and expected output [1]. ...
> It expects the output to be in the same encoding as $charset.
> Mutt performs the RFC2047 encoding automatically.

On Thu, Jan 24, 2013 at 07:00:53PM +0000, Michael Elkins wrote:
> On Thu, Jan 24, 2013 at 01:42:34PM -0500, W. Trevor King wrote:
> > ...Is it also $charset for the argv input?
> Yes.

If you don't specify a $charset in your Mutt config, you can probably
get away with not specifying charsets for these config options,
because Mutt's default charset detection will likely match up with
Python's locale.getpreferredencoding().


9 years agoREADME: Fix '' -> '' typos
W. Trevor King [Sun, 20 Jan 2013 20:36:32 +0000 (15:36 -0500)]
README: Fix '' -> '' typos

These are out of date after:

  commit d3879f6e4509c35f0bcb79e0e4eb99a1d767fd35
  Author: W. Trevor King <>
  Date:   Sun Jan 20 14:13:42 2013 -0500 Rename with underscore for package import

9 years ago.gitignore: Ignore distutils' build output
W. Trevor King [Sun, 20 Jan 2013 19:54:25 +0000 (14:54 -0500)]
.gitignore: Ignore distutils' build output

9 years Distribute COPYING
W. Trevor King [Sun, 20 Jan 2013 19:53:43 +0000 (14:53 -0500)] Distribute COPYING

9 years agoCOPYING: Add text of GPLv3
W. Trevor King [Sun, 20 Jan 2013 19:53:13 +0000 (14:53 -0500)]
COPYING: Add text of GPLv3

9 years agoREADME.rst: Add symlink for GitHub rendering
W. Trevor King [Sun, 20 Jan 2013 19:49:54 +0000 (14:49 -0500)]
README.rst: Add symlink for GitHub rendering

9 years agoREADME: Every stand-alone project desrves one
W. Trevor King [Sun, 20 Jan 2013 19:25:23 +0000 (14:25 -0500)]
README: Every stand-alone project desrves one

This is based on my usual template.  I also simplified the docstring
in to stay DRY, since that information is now in the

9 years ago.gitignore: Ignore *.pyc (generated when you run
W. Trevor King [Sun, 20 Jan 2013 19:25:01 +0000 (14:25 -0500)]
.gitignore: Ignore *.pyc (generated when you run

9 years Package Mutt-LDAP using distutils
W. Trevor King [Sun, 20 Jan 2013 19:23:21 +0000 (14:23 -0500)] Package Mutt-LDAP using distutils

9 years Rename with underscore for package import
W. Trevor King [Sun, 20 Jan 2013 19:13:42 +0000 (14:13 -0500)] Rename with underscore for package import

If I'm breaking Mutt-LDAP as a stand-alone package, I should probably
make it importable.  Even if nobody else imports it, we can still want
this for installation.

9 years agoCachedLDAPConnection: Lazy LDAP connections
W. Trevor King [Sun, 20 Jan 2013 17:59:40 +0000 (12:59 -0500)]
CachedLDAPConnection: Lazy LDAP connections

This is faster, and it allows us to return cached results even when
the LDAP server is not available (e.g. if your network is down).

9 years agoAdd logging to stdout (via StreamHandler)
W. Trevor King [Sun, 20 Jan 2013 17:50:10 +0000 (12:50 -0500)]
Add logging to stdout (via StreamHandler)

This makes it easy to trace execution and make sure everything is
happening as you think it should.  There's currently no command-line
switch to increase verbosity.  Once we drop support for Python 2.6,
I'll put in an argparse.ArgumentParser.

9 years agoCachedLDAPConnection: Convert cache format from Pickle to JSON
W. Trevor King [Sun, 20 Jan 2013 16:55:54 +0000 (11:55 -0500)]
CachedLDAPConnection: Convert cache format from Pickle to JSON

Now that we're only storing text fields (via the cache.fields
configuration setting), this is pretty easy to change.

9 years agoCachedLDAPConnection: Drop the old cache on version missmatch
W. Trevor King [Sun, 20 Jan 2013 16:48:11 +0000 (11:48 -0500)]
CachedLDAPConnection: Drop the old cache on version missmatch

The expected CachedLDAPConnection._cache_version tracks __version__,
so if you bump __version__, you invalidate the existing cache.  There
shouldn't be anything critical in the cache, and this is safer than
trying to remember to bump an independent _cache_version after major

9 years agoAdd a __version__ (for easier compatibility tracking)
W. Trevor King [Sun, 20 Jan 2013 16:47:38 +0000 (11:47 -0500)]
Add a __version__ (for easier compatibility tracking)

9 years agoCachedLDAPConnection: Add support for cache.longevity-days
W. Trevor King [Sun, 20 Jan 2013 16:39:50 +0000 (11:39 -0500)]
CachedLDAPConnection: Add support for cache.longevity-days

Cull entries older than longevity-days (defaults to 14).  This
requires changing the cache values from a list of entries to a dict
with 'time' and 'entries' keys.  Hmm, I should probably add a
reasonable cache versioning scheme...

9 years agoPrefix imported modules with underscores
W. Trevor King [Sun, 20 Jan 2013 16:25:40 +0000 (11:25 -0500)]
Prefix imported modules with underscores

This cleans up the namespace inside the module, and makes it less
likely that you'll clobber an imported module with a local variable
name.  I also removed imports for modules we no longer use.

9 years agoAlphebetize standard library imports
W. Trevor King [Sun, 20 Jan 2013 16:22:39 +0000 (11:22 -0500)]
Alphebetize standard library imports

9 years agoUse hyphenated configuration options (instead of underscores)
W. Trevor King [Sun, 20 Jan 2013 16:19:12 +0000 (11:19 -0500)]
Use hyphenated configuration options (instead of underscores)

I like them better ;).

9 years agoCachedLDAPConnection: Don't cache fields we don't use
W. Trevor King [Sun, 20 Jan 2013 16:07:50 +0000 (11:07 -0500)]
CachedLDAPConnection: Don't cache fields we don't use

I had previously said:
> It would be nice to automatically detect and drop any non text
> fields, but that's probably not worth the trouble either...

Since the configuration ID is in the cached key, we already know
exactly which fields we need to save in the cache.  Only caching those
fields avoids binary fields and fields with large values (jpegPhoto is
both).  I made the cached fields configurable because the
CachedLDAPConnection instance doesn't know about the fields needed by
format_entry() and format_columns().  If you don't configure the
cached fields, a minimal default is setup in the main block.

9 years agoRestructure around an LDAPConnection class
W. Trevor King [Sun, 20 Jan 2013 15:48:19 +0000 (10:48 -0500)]
Restructure around an LDAPConnection class

This keeps us organized and simplifies the connection API (using the
'with' statement).

I also simplified the cache structure to keep all cached entries in a
single pickled dict, to avoid calculating safe filenames for each
query.  The number of queries you make in 14 days will probably not be
large enough for any fan-out efficiencies to be worth the trouble.

I considered using JSON instead of Pickle, but JSON does not support
raw byte strings (e.g. jpegPhoto), and it's not worth encoding
non-text fields using Base64, etc., when Pickle already works.

It would be nice to automatically detect and drop any non text fields,
but that's probably not worth the trouble either...

9 years agoDecode search results to Unicode and print as Unicode
W. Trevor King [Sun, 20 Jan 2013 14:33:47 +0000 (09:33 -0500)]
Decode search results to Unicode and print as Unicode

LDAPv3 strings are encoded in UTF-8 [1], so use that encoding to
decode them in format_columns().  Adjust format_entry() and the main
block to handle the Unicode output from format_columns().


9 years agoBump my copyright to 2013 and add Niels de Vos
W. Trevor King [Sun, 20 Jan 2013 13:35:03 +0000 (08:35 -0500)]
Bump my copyright to 2013 and add Niels de Vos

9 years agoAdapt to Unicode sys.argv
W. Trevor King [Sun, 20 Jan 2013 13:34:13 +0000 (08:34 -0500)]
Adapt to Unicode sys.argv

9 years agoConvert sys.argv to Unicode (using a configurable encoding)
W. Trevor King [Sun, 20 Jan 2013 13:26:54 +0000 (08:26 -0500)]
Convert sys.argv to Unicode (using a configurable encoding)

In Python 3, sys.argv is already Unicode, but there's no clean way to
do this automatically in Python 2 [1].  If your system doesn't use
UTF-8 for it's argv encoding, you should set system.argv-encoding in
your ~/.mutt-ldap.rc.  For example, if your system uses UTF-16, try:

  argv-encoding = utf-16


9 years agosearch: Move asynchronous result handling inside search()
W. Trevor King [Sun, 20 Jan 2013 13:22:38 +0000 (08:22 -0500)]
search: Move asynchronous result handling inside search()

The result of search() should be an iterable returning entries.  If we
want to use the asynchronous and
connection.result(), that's fine, but we should handle the result
unpacking inside search().

One benefit to Wade's new generator approach is that we can start
formatting early entries while we wait for later entries to arrive.

9 years agosearch: `post` and `query` should be Unicode strings
W. Trevor King [Sun, 20 Jan 2013 12:03:29 +0000 (07:03 -0500)]
search: `post` and `query` should be Unicode strings

They're being formatted into the Unicode `filterstr`.  Being explicit
here should make the transition to Python 3 less annoying.

9 years agoMerge remote-tracking branch 'wberrier/master' into master
W. Trevor King [Sun, 20 Jan 2013 17:17:57 +0000 (12:17 -0500)]
Merge remote-tracking branch 'wberrier/master' into master

* wberrier/master:
  prevent an error when no search string is given
  Return partial results if the search takes a long time
  implement caching system for big/slow ldap servers
  make search fields configurable
  Add support for an optional display column
  Fix for python 2.6: add position indexes to format strings
  Add query filter section (in order to pare down results)
  Return results in a format that mutt expects
  fix typo in reference to .rc file
  Add Wade Berrier (me) to author/copyright list

9 years agoprevent an error when no search string is given
Niels de Vos [Thu, 13 Dec 2012 09:35:05 +0000 (10:35 +0100)]
prevent an error when no search string is given

9 years agoReturn partial results if the search takes a long time
Wade Berrier [Sun, 20 Jan 2013 02:54:43 +0000 (19:54 -0700)]
Return partial results if the search takes a long time

An impartial result is better than no result.  Done by requiring search
to have a pre-allocated connection.

9 years agoimplement caching system for big/slow ldap servers
Wade Berrier [Wed, 27 Jun 2012 16:10:42 +0000 (10:10 -0600)]
implement caching system for big/slow ldap servers

9 years agomake search fields configurable
Wade Berrier [Wed, 27 Jun 2012 07:33:11 +0000 (01:33 -0600)]
make search fields configurable

9 years agoAdd support for an optional display column
Wade Berrier [Sun, 20 Jan 2013 01:34:51 +0000 (18:34 -0700)]
Add support for an optional display column

Again, according to

9 years agoFix for python 2.6: add position indexes to format strings
Wade Berrier [Sun, 20 Jan 2013 01:02:10 +0000 (18:02 -0700)]
Fix for python 2.6: add position indexes to format strings

Turns out that omitting the indexes is only supported in python >= 2.7

It's possible this script would work with python < 2.6 but the old
format strings would be necessary

9 years agoAdd query filter section (in order to pare down results)
Wade Berrier [Sat, 19 Jan 2013 21:05:59 +0000 (14:05 -0700)]
Add query filter section (in order to pare down results)

9 years agoReturn results in a format that mutt expects
Wade Berrier [Sat, 19 Jan 2013 20:55:41 +0000 (13:55 -0700)]
Return results in a format that mutt expects

According to:

9 years agofix typo in reference to .rc file
Wade Berrier [Sat, 19 Jan 2013 20:46:28 +0000 (13:46 -0700)]
fix typo in reference to .rc file

9 years agoAdd Wade Berrier (me) to author/copyright list
Wade Berrier [Sat, 19 Jan 2013 20:44:07 +0000 (13:44 -0700)]
Add Wade Berrier (me) to author/copyright list

9 years agoposts:ldap: update Python scripts to explicitly use Python 2.
W. Trevor King [Fri, 28 Sep 2012 00:08:16 +0000 (20:08 -0400)]
posts:ldap: update Python scripts to explicitly use Python 2.

python-ldap doesn't have a Python 3 version yet.  I made a few other
changes to increase Python 3 compatibility, and added a full copyright
blurb to

9 years agoAlso search on displayName in and
W. Trevor King [Wed, 15 Aug 2012 14:13:20 +0000 (10:13 -0400)]
Also search on displayName in and

Also prefer displayName to cn when formatting names.

9 years agoAdd starttls support to and
W. Trevor King [Mon, 14 May 2012 13:21:57 +0000 (09:21 -0400)]
Add starttls support to and

Also remove `rdn` from the searched attributes, because I don't have
such a field in any of my schemas.

9 years agoAdd auth.gssapi option to (for use with Kerberos).
W. Trevor King [Fri, 11 May 2012 06:10:12 +0000 (02:10 -0400)]
Add auth.gssapi option to (for use with Kerberos).

9 years agoAdd GnuTLS and secure LDAP information.
W. Trevor King [Tue, 21 Jun 2011 12:26:01 +0000 (08:26 -0400)]
Add GnuTLS and secure LDAP information.

9 years agoAdd
W. Trevor King [Sat, 18 Jun 2011 18:32:05 +0000 (14:32 -0400)]