python bindings for libassuan

Ben McGinnes ben at
Fri May 8 20:57:48 CEST 2015

On 9/05/2015 12:56 am, Daniel Kahn Gillmor wrote:
> On Fri 2015-05-08 09:29:04 -0400, Ben McGinnes wrote:
>> Excellent, I'll definitely take a peek at that.  Did you opt for
>> ctypes, the plain Python C-API or one of the other solutions?
> The plain Python C-API.  I tend to find ctypes mappings not very
> pythonic, especially for libraries with interesting/complex C workflows
> like libassuan.

Yeah, ctypes seem okay for small, relatively constrained things and
can easily break.  The VideoLAN project uses them for the python
bondings in libvlc and, which all looked great until they
released 2.2 and it keeled over.

> For example, ctypes for the assuan_transact(), with its C function
> pointers and void* would be deeply weird in python (or at least i
> couldn't figure out how to make that seem sensible).  Instead, I made a
> python object assuan.context, which has python methods which get called
> during a transaction.

Right, and None might do it, maybe.  If not, then what?  Defining
void?  Just thinking about trying something like that makes my head

From the gpgme side of things, in spite of the weekend's effort with
porting PyME, it's pretty clear that that's more a stop-gap measure
than a long term solution.  It'll do for now, of course, but I think
people expect a little more from APIs these days than they did a
decade and a half ago.

I strongly suspect that wiping the slate clean and writing a "proper"
Python driven API, as Werner suggested, would've had to be done
anyway.  Doing all that as C-API modules, however, is a ridiculously
mammoth undertaking, so in that case something which lends itself a
little more towards a reasonable development timeframe is far more
likely.  The two options currently under consideration are Cython and
CFFI, even though neither are part of the standard library.

With CFFI it would necessitate non-standard requirements, while Cython
has its own fusion of C and Python for its code; CFFI can be written
entirely in Python and will even work with PyPY, while Cython will
generate C with which to take the gpgme libs and make the relevant
CPython modules (Cython would only need to be installed by people
developing the API/bindings, not by every end user).  Both have their
advantages, of course, and both lend themselves to aiding a developer
whose Python is pretty good, but whose work with C tends more towards
troubleshooting kernels rather than actually writing anything with it
(mostly).  Anyway, there's other overhauling to be done in gpgme, so I
can continue to evaluate all the contenders and plan ahead in that
time.  Although SWIG is already out; that's what PyME uses currently
and while it was the only real option for a long time, there are
better options available now.

>>> I've targeted Python 3, and haven't bothered to try to make it work on
>>> Python 2.x.
>> As long as it doesn't get too complex you can probably get Python 2.7
>> covered by including the UTF-8 encoding near the top of each file and
>> including "from __future__ import unicode_literals".
> Ah, i'm less concerned about the pure-python parts of it than the C-API,
> which i think might have changed incompatibly between 2 and 3 (so i
> don't want to uglify-up the C code with a ton of nasty #ifdefs --

At this point I think Python should be well on the way to getting most
people away from 2.7 and really leaving it just to those few legacy
deployments that can't shift for whatever reason.  The rest of us can
enjoy the 21st century.

> but if someone sends clean-ish patches to make it compile correctly
> against python2, though, i would definitely accept them.

Well, of course, presumably someone in legacy land will do that
eventually.  Either that or they'll remember the python is a brilliant
glue language and get their python 2 things to interact with the
python 3 bits.

> Well, for gpg, it's all doing subprocess calls to the gpg binary
> somehow, whether that's managed through gpgme or in python directly :/

Yes, but only one of these two is more likely to give someone shell
access if that was not the intent.

> Please let me know what you think after taking a look at it!  Hopefully
> gnupg-devel is an OK place for this discussion for now.

I can't think of anywhere better.  So I think we're good, and threads
are easy enough to ignore or mark as read.

I also have your first patch for you if there's somewhere I can push
it to.  It's not much, just a more pythonic way of specifying the
homedir in assuan/  The relevant bits are attached.

-------------- next part --------------
commit 9bdbee54fbfa08f795e62b15adc9944b55ade7be
Author: Ben McGinnes <ben at>
Date:   Sat May 9 03:53:47 2015 +1000

    Pythonic homedir
    * Narrowed os.path import.
    * Replaced getenv calls and $HOME with os.path.expanduser().
    * Added generic (not guaranteed to work) homedir for Windows.

commit 2a7557d1434bbfca4100ef63720d900320b8da8a
Author: Daniel Kahn Gillmor <dkg at>
Date:   Wed May 6 17:51:46 2015 -0400

    prettify the example and the comments further

-------------- next part --------------
diff --git a/assuan/ b/assuan/
index 14328af..026e904 100644
--- a/assuan/
+++ b/assuan/
@@ -2,17 +2,19 @@
 '''Use assuan to talk to typical GnuPG services'''
-import os
+import os.path
+import sys
 import assuan
 def sockpath(servicename, homedir=None):
     '''Given the name of a standard GnuPG daemon, guess its default socket path'''
     if (homedir is None):
-        homedir = os.path.join(os.getenv('GNUPGHOME',
-                                         os.path.join(os.getenv('HOME', '.'),
-                                           '.gnupg')))
+        home = os.path.expanduser('~')
+        if sys.platform == 'win32':
+            homedir = os.path.join(home, '/', '_gnupg')
+        else:
+            homedir = os.path.join(home, '/', '.gnupg')
     return os.path.join(homedir, "S." + servicename)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 630 bytes
Desc: OpenPGP digital signature
URL: </pipermail/attachments/20150509/6ed993eb/attachment-0001.sig>

More information about the Gnupg-devel mailing list