aboutsummaryrefslogtreecommitdiffstats
path: root/doc/gpgme-python-howto.texi
diff options
context:
space:
mode:
authorBen McGinnes <[email protected]>2018-09-16 03:48:12 +0000
committerBen McGinnes <[email protected]>2018-09-16 03:48:12 +0000
commit61c08f7435570783f5c267e42d288d31bf77e560 (patch)
tree63b9fc79d4b9e092bd5cc705a6ceb6ec851737a8 /doc/gpgme-python-howto.texi
parentdocs: even more edits (diff)
downloadgpgme-61c08f7435570783f5c267e42d288d31bf77e560.tar.gz
gpgme-61c08f7435570783f5c267e42d288d31bf77e560.zip
docs: python bindings howto
* Added new advanced section with an example of using the Python bindings with CPython code compiled back to C code using Cython. * Though it may seem a bit counter-intuitive to use the bindings just to go back to C via a different route, this is not actually stupid. * Added examples/howto/advanced/cython/ directory. * Added keycount.pyx, setup.py and the keycount.c file which the first two generated with Cython. Not including the .so and .o files from the build. * Exported the .texi version of the howto for the main docs.
Diffstat (limited to 'doc/gpgme-python-howto.texi')
-rw-r--r--doc/gpgme-python-howto.texi119
1 files changed, 119 insertions, 0 deletions
diff --git a/doc/gpgme-python-howto.texi b/doc/gpgme-python-howto.texi
index 7b19f72d..d80cf37f 100644
--- a/doc/gpgme-python-howto.texi
+++ b/doc/gpgme-python-howto.texi
@@ -27,6 +27,7 @@
* Working with keys::
* Basic Functions::
* Creating keys and subkeys::
+* Advanced or Experimental Use Cases::
* Miscellaneous work-arounds::
* Copyright and Licensing::
@@ -120,6 +121,10 @@ User IDs
* Adding User IDs::
* Revokinging User IDs::
+Advanced or Experimental Use Cases
+
+* C plus Python plus SWIG plus Cython::
+
Miscellaneous work-arounds
* Group lines::
@@ -2061,6 +2066,120 @@ key = c.get_key(dmfpr, secret=True)
c.key_sign(key, uids=uid, expires_in=2764800)
@end example
+@node Advanced or Experimental Use Cases
+@chapter Advanced or Experimental Use Cases
+
+@menu
+* C plus Python plus SWIG plus Cython::
+@end menu
+
+@node C plus Python plus SWIG plus Cython
+@section C plus Python plus SWIG plus Cython
+
+In spite of my near facetious commentary in @ref{CFFI is the Bestâ„¢ and GPGME should use it instead of SWIG, , an earlier section}, it is
+in fact quite possible to use the GPGME bindings with @uref{http://docs.cython.org/en/latest/index.html, Cython}. In many
+cases the benefits may not be obvious since the most computationally
+intensive work never leaves the level of the C code with which GPGME
+itself is interacting with.
+
+Nevertheless, there are some situations where the benefits are
+demonstrable. One of the better and easier examples being the one of
+the early examples in this HOWTO, the @ref{Counting keys, , key counting} code. Running that
+example as an executable Python script, @samp{keycount.py} (available in
+the @samp{examples/howto/} directory), will take a noticable amount of time
+to run on most systems where the public keybox or keyring contains a
+few thousand public keys.
+
+Earlier in the evening I ran that script on my laptop, as I tend to do
+periodically and timed it using @samp{time} utility, with the following
+results:
+
+@example
+bash-4.4$ time keycount.py
+
+Number of secret keys: 23
+Number of public keys: 12112
+
+
+real 11m52.945s
+user 0m0.913s
+sys 0m0.752s
+
+bash-4.4$
+@end example
+
+Sometime after that I imported another key and followed it with a
+little test of Cython. This test was kept fairly basic, essentially
+lifting the material from the initial @uref{http://docs.cython.org/en/latest/src/tutorial/cython_tutorial.html#cython-hello-world, Cython Hello World tutorial} to
+demonstrate compiling Python code to C. The first step was to take
+the example key counting code quoted previously, essentially from the
+importing of the @samp{gpg} module to the end of the script:
+
+@example
+import gpg
+
+c = gpg.Context()
+seckeys = c.keylist(pattern=None, secret=True)
+pubkeys = c.keylist(pattern=None, secret=False)
+
+seclist = list(seckeys)
+secnum = len(seclist)
+
+publist = list(pubkeys)
+pubnum = len(publist)
+
+print("""
+ Number of secret keys: @{0@}
+ Number of public keys: @{1@}
+""".format(secnum, pubnum))
+@end example
+
+Save that into a file called @samp{keycount.pyx} and then create a
+@samp{setup.py} file which contains this:
+
+@example
+from distutils.core import setup
+from Cython.Build import cythonize
+
+setup(
+ ext_modules = cythonize("keycount.pyx")
+)
+@end example
+
+Compile it:
+
+@example
+bash-4.4$ python setup.py build_ext --inplace
+bash-4.4$
+@end example
+
+Then run it in a similar manner to @samp{keycount.py}:
+
+@example
+bash-4.4$ time python3.7 -c "import keycount"
+
+Number of secret keys: 23
+Number of public keys: 12113
+
+
+real 6m47.905s
+user 0m0.785s
+sys 0m0.331s
+
+bash-4.4$
+@end example
+
+Cython turned @samp{keycount.pyx} into an 81KB @samp{keycount.o} file in the
+@samp{build/} directory, a 24KB @samp{keycount.cpython-37m-darwin.so} file to be
+imported into Python 3.7 and a 113KB @samp{keycount.c} generated C source
+code file of nearly three thousand lines. Quite a bit bigger than the
+314 bytes of the @samp{keycount.pyx} file or the full 1,452 bytes of the
+full executable @samp{keycount.py} example script.
+
+On the other hand it ran in nearly half the time; taking 6 minutes and
+47.905 seconds to run. As opposed to the 11 minutes and 52.945 seconds
+which the CPython script alone took.
+
@node Miscellaneous work-arounds
@chapter Miscellaneous work-arounds