python bindings: core — PEP8 compliance
[gpgme.git] / lang / python / src / core.py
1 # -*- coding: utf-8 -*-
2
3 import re
4 import os
5 import warnings
6 import weakref
7
8 from . import gpgme
9 from .errors import errorcheck, GPGMEError
10 from . import constants
11 from . import errors
12 from . import util
13
14 from __future__ import absolute_import, print_function, unicode_literals
15 del absolute_import, print_function, unicode_literals
16
17 # Copyright (C) 2016-2017 g10 Code GmbH
18 # Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
19 # Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
20 #
21 #    This library is free software; you can redistribute it and/or
22 #    modify it under the terms of the GNU Lesser General Public
23 #    License as published by the Free Software Foundation; either
24 #    version 2.1 of the License, or (at your option) any later version.
25 #
26 #    This library is distributed in the hope that it will be useful,
27 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
28 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29 #    Lesser General Public License for more details.
30 #
31 #    You should have received a copy of the GNU Lesser General Public
32 #    License along with this library; if not, write to the Free Software
33 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
34
35 """Core functionality
36
37 Core functionality of GPGME wrapped in a object-oriented fashion.
38 Provides the 'Context' class for performing cryptographic operations,
39 and the 'Data' class describing buffers of data.
40
41 """
42
43
44 class GpgmeWrapper(object):
45     """Base wrapper class
46
47     Not to be instantiated directly.
48
49     """
50
51     def __init__(self, wrapped):
52         self._callback_excinfo = None
53         self.wrapped = wrapped
54
55     def __repr__(self):
56         return '<{}/{!r}>'.format(super(GpgmeWrapper, self).__repr__(),
57                                   self.wrapped)
58
59     def __str__(self):
60         acc = ['{}.{}'.format(__name__, self.__class__.__name__)]
61         flags = [f for f in self._boolean_properties if getattr(self, f)]
62         if flags:
63             acc.append('({})'.format(' '.join(flags)))
64
65         return '<{}>'.format(' '.join(acc))
66
67     def __hash__(self):
68         return hash(repr(self.wrapped))
69
70     def __eq__(self, other):
71         if other is None:
72             return False
73         else:
74             return repr(self.wrapped) == repr(other.wrapped)
75
76     @property
77     def _ctype(self):
78         """The name of the c type wrapped by this class
79
80         Must be set by child classes.
81
82         """
83         raise NotImplementedError()
84
85     @property
86     def _cprefix(self):
87         """The common prefix of c functions wrapped by this class
88
89         Must be set by child classes.
90
91         """
92         raise NotImplementedError()
93
94     def _errorcheck(self, name):
95         """Must be implemented by child classes.
96
97         This function must return a trueish value for all c functions
98         returning gpgme_error_t."""
99         raise NotImplementedError()
100
101     """The set of all boolean properties"""
102     _boolean_properties = set()
103
104     def __wrap_boolean_property(self, key, do_set=False, value=None):
105         get_func = getattr(gpgme,
106                            "{}get_{}".format(self._cprefix, key))
107         set_func = getattr(gpgme,
108                            "{}set_{}".format(self._cprefix, key))
109
110         def get(slf):
111             return bool(get_func(slf.wrapped))
112
113         def set_(slf, value):
114             set_func(slf.wrapped, bool(value))
115
116         p = property(get, set_, doc="{} flag".format(key))
117         setattr(self.__class__, key, p)
118
119         if do_set:
120             set_(self, bool(value))
121         else:
122             return get(self)
123
124     _munge_docstring = re.compile(r'gpgme_([^(]*)\(([^,]*), (.*\) -> .*)')
125
126     def __getattr__(self, key):
127         """On-the-fly generation of wrapper methods and properties"""
128         if key[0] == '_' or self._cprefix is None:
129             return None
130
131         if key in self._boolean_properties:
132             return self.__wrap_boolean_property(key)
133
134         name = self._cprefix + key
135         func = getattr(gpgme, name)
136
137         if self._errorcheck(name):
138             def _funcwrap(slf, *args):
139                 result = func(slf.wrapped, *args)
140                 if slf._callback_excinfo:
141                     gpgme.gpg_raise_callback_exception(slf)
142                 return errorcheck(result, name)
143         else:
144             def _funcwrap(slf, *args):
145                 result = func(slf.wrapped, *args)
146                 if slf._callback_excinfo:
147                     gpgme.gpg_raise_callback_exception(slf)
148                 return result
149
150         doc = self._munge_docstring.sub(r'\2.\1(\3', getattr(func, "__doc__"))
151         _funcwrap.__doc__ = doc
152
153         # Monkey-patch the class.
154         setattr(self.__class__, key, _funcwrap)
155
156         # Bind the method to 'self'.
157         def wrapper(*args):
158             return _funcwrap(self, *args)
159         wrapper.__doc__ = doc
160
161         return wrapper
162
163     def __setattr__(self, key, value):
164         """On-the-fly generation of properties"""
165         if key in self._boolean_properties:
166             self.__wrap_boolean_property(key, True, value)
167         else:
168             super(GpgmeWrapper, self).__setattr__(key, value)
169
170
171 class Context(GpgmeWrapper):
172     """Context for cryptographic operations
173
174     All cryptographic operations in GPGME are performed within a
175     context, which contains the internal state of the operation as
176     well as configuration parameters.  By using several contexts you
177     can run several cryptographic operations in parallel, with
178     different configuration.
179
180     Access to a context must be synchronized.
181
182     """
183
184     def __init__(self, armor=False, textmode=False, offline=False,
185                  signers=[], pinentry_mode=constants.PINENTRY_MODE_DEFAULT,
186                  protocol=constants.PROTOCOL_OpenPGP,
187                  wrapped=None, home_dir=None):
188         """Construct a context object
189
190         Keyword arguments:
191         armor           -- enable ASCII armoring (default False)
192         textmode        -- enable canonical text mode (default False)
193         offline         -- do not contact external key sources (default False)
194         signers         -- list of keys used for signing (default [])
195         pinentry_mode   -- pinentry mode (default PINENTRY_MODE_DEFAULT)
196         protocol        -- protocol to use (default PROTOCOL_OpenPGP)
197         home_dir        -- state directory (default is the engine default)
198
199         """
200         if wrapped:
201             self.own = False
202         else:
203             tmp = gpgme.new_gpgme_ctx_t_p()
204             errorcheck(gpgme.gpgme_new(tmp))
205             wrapped = gpgme.gpgme_ctx_t_p_value(tmp)
206             gpgme.delete_gpgme_ctx_t_p(tmp)
207             self.own = True
208         super(Context, self).__init__(wrapped)
209         self.armor = armor
210         self.textmode = textmode
211         self.offline = offline
212         self.signers = signers
213         self.pinentry_mode = pinentry_mode
214         self.protocol = protocol
215         self.home_dir = home_dir
216
217     def __read__(self, sink, data):
218         """Read helper
219
220         Helper function to retrieve the results of an operation, or
221         None if SINK is given.
222         """
223         if sink or data is None:
224             return None
225         data.seek(0, os.SEEK_SET)
226         return data.read()
227
228     def __repr__(self):
229         return (
230             "Context(armor={0.armor}, "
231             "textmode={0.textmode}, offline={0.offline}, "
232             "signers={0.signers}, pinentry_mode={0.pinentry_mode}, "
233             "protocol={0.protocol}, home_dir={0.home_dir}"
234             ")").format(self)
235
236     def encrypt(self, plaintext, recipients=[], sign=True, sink=None,
237                 passphrase=None, always_trust=False, add_encrypt_to=False,
238                 prepare=False, expect_sign=False, compress=True):
239         """Encrypt data
240
241         Encrypt the given plaintext for the given recipients.  If the
242         list of recipients is empty, the data is encrypted
243         symmetrically with a passphrase.
244
245         The passphrase can be given as parameter, using a callback
246         registered at the context, or out-of-band via pinentry.
247
248         Keyword arguments:
249         recipients      -- list of keys to encrypt to
250         sign            -- sign plaintext (default True)
251         sink            -- write result to sink instead of returning it
252         passphrase      -- for symmetric encryption
253         always_trust    -- always trust the keys (default False)
254         add_encrypt_to  -- encrypt to configured additional keys (default False)
255         prepare         -- (ui) prepare for encryption (default False)
256         expect_sign     -- (ui) prepare for signing (default False)
257         compress        -- compress plaintext (default True)
258
259         Returns:
260         ciphertext      -- the encrypted data (or None if sink is given)
261         result          -- additional information about the encryption
262         sign_result     -- additional information about the signature(s)
263
264         Raises:
265         InvalidRecipients -- if encryption using a particular key failed
266         InvalidSigners  -- if signing using a particular key failed
267         GPGMEError      -- as signaled by the underlying library
268
269         """
270         ciphertext = sink if sink else Data()
271         flags = 0
272         flags |= always_trust * constants.ENCRYPT_ALWAYS_TRUST
273         flags |= (not add_encrypt_to) * constants.ENCRYPT_NO_ENCRYPT_TO
274         flags |= prepare * constants.ENCRYPT_PREPARE
275         flags |= expect_sign * constants.ENCRYPT_EXPECT_SIGN
276         flags |= (not compress) * constants.ENCRYPT_NO_COMPRESS
277
278         if passphrase is not None:
279             old_pinentry_mode = self.pinentry_mode
280             old_passphrase_cb = getattr(self, '_passphrase_cb', None)
281             self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
282
283             def passphrase_cb(hint, desc, prev_bad, hook=None):
284                 return passphrase
285             self.set_passphrase_cb(passphrase_cb)
286
287         try:
288             if sign:
289                 self.op_encrypt_sign(recipients, flags, plaintext, ciphertext)
290             else:
291                 self.op_encrypt(recipients, flags, plaintext, ciphertext)
292         except errors.GPGMEError as e:
293             result = self.op_encrypt_result()
294             sig_result = self.op_sign_result() if sign else None
295             results = (self.__read__(sink, ciphertext),
296                        result, sig_result)
297             if e.getcode() == errors.UNUSABLE_PUBKEY:
298                 if result.invalid_recipients:
299                     raise errors.InvalidRecipients(result.invalid_recipients,
300                                                    error=e.error,
301                                                    results=results)
302             if e.getcode() == errors.UNUSABLE_SECKEY:
303                 sig_result = self.op_sign_result()
304                 if sig_result.invalid_signers:
305                     raise errors.InvalidSigners(sig_result.invalid_signers,
306                                                 error=e.error,
307                                                 results=results)
308             # Otherwise, just raise the error, but attach the results
309             # first.
310             e.results = results
311             raise e
312         finally:
313             if passphrase is not None:
314                 self.pinentry_mode = old_pinentry_mode
315                 if old_passphrase_cb:
316                     self.set_passphrase_cb(*old_passphrase_cb[1:])
317
318         result = self.op_encrypt_result()
319         assert not result.invalid_recipients
320         sig_result = self.op_sign_result() if sign else None
321         assert not sig_result or not sig_result.invalid_signers
322
323         return self.__read__(sink, ciphertext), result, sig_result
324
325     def decrypt(self, ciphertext, sink=None, passphrase=None, verify=True):
326         """Decrypt data
327
328         Decrypt the given ciphertext and verify any signatures.  If
329         VERIFY is an iterable of keys, the ciphertext must be signed
330         by all those keys, otherwise an error is raised.
331
332         If the ciphertext is symmetrically encrypted using a
333         passphrase, that passphrase can be given as parameter, using a
334         callback registered at the context, or out-of-band via
335         pinentry.
336
337         Keyword arguments:
338         sink            -- write result to sink instead of returning it
339         passphrase      -- for symmetric decryption
340         verify          -- check signatures (default True)
341
342         Returns:
343         plaintext       -- the decrypted data (or None if sink is given)
344         result          -- additional information about the decryption
345         verify_result   -- additional information about the signature(s)
346
347         Raises:
348         UnsupportedAlgorithm -- if an unsupported algorithm was used
349         BadSignatures   -- if a bad signature is encountered
350         MissingSignatures -- if expected signatures are missing or bad
351         GPGMEError      -- as signaled by the underlying library
352
353         """
354         plaintext = sink if sink else Data()
355
356         if passphrase is not None:
357             old_pinentry_mode = self.pinentry_mode
358             old_passphrase_cb = getattr(self, '_passphrase_cb', None)
359             self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
360
361             def passphrase_cb(hint, desc, prev_bad, hook=None):
362                 return passphrase
363             self.set_passphrase_cb(passphrase_cb)
364
365         try:
366             if verify:
367                 self.op_decrypt_verify(ciphertext, plaintext)
368             else:
369                 self.op_decrypt(ciphertext, plaintext)
370         except errors.GPGMEError as e:
371             result = self.op_decrypt_result()
372             verify_result = self.op_verify_result() if verify else None
373             # Just raise the error, but attach the results first.
374             e.results = (self.__read__(sink, plaintext),
375                          result, verify_result)
376             raise e
377         finally:
378             if passphrase is not None:
379                 self.pinentry_mode = old_pinentry_mode
380                 if old_passphrase_cb:
381                     self.set_passphrase_cb(*old_passphrase_cb[1:])
382
383         result = self.op_decrypt_result()
384         verify_result = self.op_verify_result() if verify else None
385         results = (self.__read__(sink, plaintext), result, verify_result)
386         if result.unsupported_algorithm:
387             raise errors.UnsupportedAlgorithm(result.unsupported_algorithm,
388                                               results=results)
389
390         if verify:
391             if any(s.status != errors.NO_ERROR
392                    for s in verify_result.signatures):
393                 raise errors.BadSignatures(verify_result, results=results)
394
395         if not verify:  # was: if verify and verify != True:
396             missing = list()
397             for key in verify:
398                 ok = False
399                 for subkey in key.subkeys:
400                     for sig in verify_result.signatures:
401                         if sig.summary & constants.SIGSUM_VALID == 0:
402                             continue
403                         if subkey.can_sign and subkey.fpr == sig.fpr:
404                             ok = True
405                             break
406                     if ok:
407                         break
408                 if not ok:
409                     missing.append(key)
410             if missing:
411                 raise errors.MissingSignatures(verify_result, missing,
412                                                results=results)
413
414         return results
415
416     def sign(self, data, sink=None, mode=constants.SIG_MODE_NORMAL):
417         """Sign data
418
419         Sign the given data with either the configured default local
420         key, or the 'signers' keys of this context.
421
422         Keyword arguments:
423         mode            -- signature mode (default: normal, see below)
424         sink            -- write result to sink instead of returning it
425
426         Returns:
427         either
428           signed_data   -- encoded data and signature (normal mode)
429           signature     -- only the signature data (detached mode)
430           cleartext     -- data and signature as text (cleartext mode)
431             (or None if sink is given)
432         result          -- additional information about the signature(s)
433
434         Raises:
435         InvalidSigners  -- if signing using a particular key failed
436         GPGMEError      -- as signaled by the underlying library
437
438         """
439         signeddata = sink if sink else Data()
440
441         try:
442             self.op_sign(data, signeddata, mode)
443         except errors.GPGMEError as e:
444             results = (self.__read__(sink, signeddata),
445                        self.op_sign_result())
446             if e.getcode() == errors.UNUSABLE_SECKEY:
447                 if results[1].invalid_signers:
448                     raise errors.InvalidSigners(results[1].invalid_signers,
449                                                 error=e.error,
450                                                 results=results)
451             e.results = results
452             raise e
453
454         result = self.op_sign_result()
455         assert not result.invalid_signers
456
457         return self.__read__(sink, signeddata), result
458
459     def verify(self, signed_data, signature=None, sink=None, verify=[]):
460         """Verify signatures
461
462         Verify signatures over data.  If VERIFY is an iterable of
463         keys, the ciphertext must be signed by all those keys,
464         otherwise an error is raised.
465
466         Keyword arguments:
467         signature       -- detached signature data
468         sink            -- write result to sink instead of returning it
469
470         Returns:
471         data            -- the plain data
472             (or None if sink is given, or we verified a detached signature)
473         result          -- additional information about the signature(s)
474
475         Raises:
476         BadSignatures   -- if a bad signature is encountered
477         MissingSignatures -- if expected signatures are missing or bad
478         GPGMEError      -- as signaled by the underlying library
479
480         """
481         if signature:
482             # Detached signature, we don't return the plain text.
483             data = None
484         else:
485             data = sink if sink else Data()
486
487         try:
488             if signature:
489                 self.op_verify(signature, signed_data, None)
490             else:
491                 self.op_verify(signed_data, None, data)
492         except errors.GPGMEError as e:
493             # Just raise the error, but attach the results first.
494             e.results = (self.__read__(sink, data),
495                          self.op_verify_result())
496             raise e
497
498         results = (self.__read__(sink, data), self.op_verify_result())
499         if any(s.status != errors.NO_ERROR for s in results[1].signatures):
500             raise errors.BadSignatures(results[1], results=results)
501
502         missing = list()
503         for key in verify:
504             ok = False
505             for subkey in key.subkeys:
506                 for sig in results[1].signatures:
507                     if sig.summary & constants.SIGSUM_VALID == 0:
508                         continue
509                     if subkey.can_sign and subkey.fpr == sig.fpr:
510                         ok = True
511                         break
512                 if ok:
513                     break
514             if not ok:
515                 missing.append(key)
516         if missing:
517             raise errors.MissingSignatures(results[1], missing,
518                                            results=results)
519
520         return results
521
522     def key_import(self, data):
523         """Import data
524
525         Imports the given data into the Context.
526
527         Returns:
528                 -- an object describing the results of imported or updated
529                    keys
530
531         Raises:
532         TypeError      -- Very rarely.
533         GPGMEError     -- as signaled by the underlying library:
534
535                           Import status errors, when they occur, will usually
536                           be of NODATA.  NO_PUBKEY indicates something
537                           managed to run the function without any
538                           arguments, while an argument of None triggers
539                           the first NODATA of errors.GPGME in the
540                            exception.
541         """
542         try:
543             self.op_import(data)
544             result = self.op_import_result()
545             if result.considered == 0:
546                 status = constants.STATUS_IMPORT_PROBLEM
547             else:
548                 status = constants.STATUS_KEY_CONSIDERED
549         except Exception as e:
550             if e == errors.GPGMEError:
551                 if e.code_str == "No data":
552                     status = constants.STATUS_NODATA
553                 else:
554                     status = constants.STATUS_FILE_ERROR
555             elif e == TypeError and hasattr(data, "decode") is True:
556                 status = constants.STATUS_NO_PUBKEY
557             elif e == TypeError and hasattr(data, "encode") is True:
558                 status = constants.STATUS_FILE_ERROR
559             else:
560                 status = constants.STATUS_ERROR
561
562         if status == constants.STATUS_KEY_CONSIDERED:
563             import_result = result
564         else:
565             import_result = status
566
567         return import_result
568
569     def keylist(self, pattern=None, secret=False,
570                 mode=constants.keylist.mode.LOCAL,
571                 source=None):
572         """List keys
573
574         Keyword arguments:
575         pattern -- return keys matching pattern (default: all keys)
576         secret  -- return only secret keys (default: False)
577         mode    -- keylist mode (default: list local keys)
578         source  -- read keys from source instead from the keyring
579                        (all other options are ignored in this case)
580
581         Returns:
582                 -- an iterator returning key objects
583
584         Raises:
585         GPGMEError      -- as signaled by the underlying library
586         """
587         if not source:
588             self.set_keylist_mode(mode)
589             self.op_keylist_start(pattern, secret)
590         else:
591             # Automatic wrapping of SOURCE is not possible here,
592             # because the object must not be deallocated until the
593             # iteration over the results ends.
594             if not isinstance(source, Data):
595                 source = Data(file=source)
596             self.op_keylist_from_data_start(source, 0)
597
598         key = self.op_keylist_next()
599         while key:
600             yield key
601             key = self.op_keylist_next()
602         self.op_keylist_end()
603
604     def create_key(self, userid, algorithm=None, expires_in=0, expires=True,
605                    sign=False, encrypt=False, certify=False,
606                    authenticate=False, passphrase=None, force=False):
607         """Create a primary key
608
609         Create a primary key for the user id USERID.
610
611         ALGORITHM may be used to specify the public key encryption
612         algorithm for the new key.  By default, a reasonable default
613         is chosen.  You may use "future-default" to select an
614         algorithm that will be the default in a future implementation
615         of the engine.  ALGORITHM may be a string like "rsa", or
616         "rsa2048" to explicitly request an algorithm and a key size.
617
618         EXPIRES_IN specifies the expiration time of the key in number
619         of seconds since the keys creation.  By default, a reasonable
620         expiration time is chosen.  If you want to create a key that
621         does not expire, use the keyword argument EXPIRES.
622
623         SIGN, ENCRYPT, CERTIFY, and AUTHENTICATE can be used to
624         request the capabilities of the new key.  If you don't request
625         any, a reasonable set of capabilities is selected, and in case
626         of OpenPGP, a subkey with a reasonable set of capabilities is
627         created.
628
629         If PASSPHRASE is None (the default), then the key will not be
630         protected with a passphrase.  If PASSPHRASE is a string, it
631         will be used to protect the key.  If PASSPHRASE is True, the
632         passphrase must be supplied using a passphrase callback or
633         out-of-band with a pinentry.
634
635         Keyword arguments:
636         algorithm    -- public key algorithm, see above (default: reasonable)
637         expires_in   -- expiration time in seconds (default: reasonable)
638         expires      -- whether or not the key should expire (default: True)
639         sign         -- request the signing capability (see above)
640         encrypt      -- request the encryption capability (see above)
641         certify      -- request the certification capability (see above)
642         authenticate -- request the authentication capability (see above)
643         passphrase   -- protect the key with a passphrase (default: no
644                         passphrase)
645         force        -- force key creation even if a key with the same userid
646                         exists (default: False)
647
648         Returns:
649                      -- an object describing the result of the key creation
650
651         Raises:
652         GPGMEError   -- as signaled by the underlying library
653
654         """
655         if util.is_a_string(passphrase):
656             old_pinentry_mode = self.pinentry_mode
657             old_passphrase_cb = getattr(self, '_passphrase_cb', None)
658             self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
659
660             def passphrase_cb(hint, desc, prev_bad, hook=None):
661                 return passphrase
662             self.set_passphrase_cb(passphrase_cb)
663
664         try:
665             self.op_createkey(userid, algorithm,
666                               0,  # reserved
667                               expires_in,
668                               None,  # extrakey
669                               ((constants.create.SIGN if sign else 0)
670                                | (constants.create.ENCR if encrypt else 0)
671                                | (constants.create.CERT if certify else 0)
672                                | (constants.create.AUTH if authenticate else 0)
673                                | (constants.create.NOPASSWD if passphrase is None else 0)
674                                | (0 if expires else constants.create.NOEXPIRE)
675                                | (constants.create.FORCE if force else 0)))
676         finally:
677             if util.is_a_string(passphrase):
678                 self.pinentry_mode = old_pinentry_mode
679                 if old_passphrase_cb:
680                     self.set_passphrase_cb(*old_passphrase_cb[1:])
681
682         return self.op_genkey_result()
683
684     def create_subkey(self, key, algorithm=None, expires_in=0, expires=True,
685                       sign=False, encrypt=False, authenticate=False,
686                       passphrase=None):
687         """Create a subkey
688
689         Create a subkey for the given KEY.  As subkeys are a concept
690         of OpenPGP, calling this is only valid for the OpenPGP
691         protocol.
692
693         ALGORITHM may be used to specify the public key encryption
694         algorithm for the new subkey.  By default, a reasonable
695         default is chosen.  You may use "future-default" to select an
696         algorithm that will be the default in a future implementation
697         of the engine.  ALGORITHM may be a string like "rsa", or
698         "rsa2048" to explicitly request an algorithm and a key size.
699
700         EXPIRES_IN specifies the expiration time of the subkey in
701         number of seconds since the subkeys creation.  By default, a
702         reasonable expiration time is chosen.  If you want to create a
703         subkey that does not expire, use the keyword argument EXPIRES.
704
705         SIGN, ENCRYPT, and AUTHENTICATE can be used to request the
706         capabilities of the new subkey.  If you don't request any, an
707         encryption subkey is generated.
708
709         If PASSPHRASE is None (the default), then the subkey will not
710         be protected with a passphrase.  If PASSPHRASE is a string, it
711         will be used to protect the subkey.  If PASSPHRASE is True,
712         the passphrase must be supplied using a passphrase callback or
713         out-of-band with a pinentry.
714
715         Keyword arguments:
716         algorithm    -- public key algorithm, see above (default: reasonable)
717         expires_in   -- expiration time in seconds (default: reasonable)
718         expires      -- whether or not the subkey should expire (default: True)
719         sign         -- request the signing capability (see above)
720         encrypt      -- request the encryption capability (see above)
721         authenticate -- request the authentication capability (see above)
722         passphrase   -- protect the subkey with a passphrase (default: no
723                         passphrase)
724
725         Returns:
726                      -- an object describing the result of the subkey creation
727
728         Raises:
729         GPGMEError   -- as signaled by the underlying library
730
731         """
732         if util.is_a_string(passphrase):
733             old_pinentry_mode = self.pinentry_mode
734             old_passphrase_cb = getattr(self, '_passphrase_cb', None)
735             self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
736
737             def passphrase_cb(hint, desc, prev_bad, hook=None):
738                 return passphrase
739             self.set_passphrase_cb(passphrase_cb)
740
741         try:
742             self.op_createsubkey(key, algorithm,
743                                  0,  # reserved
744                                  expires_in,
745                                  ((constants.create.SIGN if sign else 0)
746                                   | (constants.create.ENCR if encrypt else 0)
747                                   | (constants.create.AUTH if authenticate else 0)
748                                   | (constants.create.NOPASSWD
749                                      if passphrase is None else 0)
750                                   | (0 if expires else constants.create.NOEXPIRE)))
751         finally:
752             if util.is_a_string(passphrase):
753                 self.pinentry_mode = old_pinentry_mode
754                 if old_passphrase_cb:
755                     self.set_passphrase_cb(*old_passphrase_cb[1:])
756
757         return self.op_genkey_result()
758
759     def key_add_uid(self, key, uid):
760         """Add a UID
761
762         Add the uid UID to the given KEY.  Calling this function is
763         only valid for the OpenPGP protocol.
764
765         Raises:
766         GPGMEError   -- as signaled by the underlying library
767
768         """
769         self.op_adduid(key, uid, 0)
770
771     def key_revoke_uid(self, key, uid):
772         """Revoke a UID
773
774         Revoke the uid UID from the given KEY.  Calling this function
775         is only valid for the OpenPGP protocol.
776
777         Raises:
778         GPGMEError   -- as signaled by the underlying library
779
780         """
781         self.op_revuid(key, uid, 0)
782
783     def key_sign(self, key, uids=None, expires_in=False, local=False):
784         """Sign a key
785
786         Sign a key with the current set of signing keys.  Calling this
787         function is only valid for the OpenPGP protocol.
788
789         If UIDS is None (the default), then all UIDs are signed.  If
790         it is a string, then only the matching UID is signed.  If it
791         is a list of strings, then all matching UIDs are signed.  Note
792         that a case-sensitive exact string comparison is done.
793
794         EXPIRES_IN specifies the expiration time of the signature in
795         seconds.  If EXPIRES_IN is False, the signature does not
796         expire.
797
798         Keyword arguments:
799         uids         -- user ids to sign, see above (default: sign all)
800         expires_in   -- validity period of the signature in seconds
801                                                (default: do not expire)
802         local        -- create a local, non-exportable signature
803                                                (default: False)
804
805         Raises:
806         GPGMEError   -- as signaled by the underlying library
807
808         """
809         flags = 0
810         if uids is None or util.is_a_string(uids):
811             pass  # through unchanged
812         else:
813             flags |= constants.keysign.LFSEP
814             uids = "\n".join(uids)
815
816         if not expires_in:
817             flags |= constants.keysign.NOEXPIRE
818
819         if local:
820             flags |= constants.keysign.LOCAL
821
822         self.op_keysign(key, uids, expires_in, flags)
823
824     def key_tofu_policy(self, key, policy):
825         """Set a keys' TOFU policy
826
827         Set the TOFU policy associated with KEY to POLICY.  Calling
828         this function is only valid for the OpenPGP protocol.
829
830         Raises:
831         GPGMEError   -- as signaled by the underlying library
832
833         """
834         self.op_tofu_policy(key, policy)
835
836     def assuan_transact(self, command,
837                         data_cb=None, inquire_cb=None, status_cb=None):
838         """Issue a raw assuan command
839
840         This function can be used to issue a raw assuan command to the
841         engine.
842
843         If command is a string or bytes, it will be used as-is.  If it
844         is an iterable of strings, it will be properly escaped and
845         joined into an well-formed assuan command.
846
847         Keyword arguments:
848         data_cb         -- a callback receiving data lines
849         inquire_cb      -- a callback providing more information
850         status_cb       -- a callback receiving status lines
851
852         Returns:
853         result          -- the result of command as GPGMEError
854
855         Raises:
856         GPGMEError      -- as signaled by the underlying library
857
858         """
859
860         if util.is_a_string(command) or isinstance(command, bytes):
861             cmd = command
862         else:
863             cmd = " ".join(util.percent_escape(f) for f in command)
864
865         errptr = gpgme.new_gpgme_error_t_p()
866
867         err = gpgme.gpgme_op_assuan_transact_ext(
868             self.wrapped,
869             cmd,
870             (weakref.ref(self), data_cb) if data_cb else None,
871             (weakref.ref(self), inquire_cb) if inquire_cb else None,
872             (weakref.ref(self), status_cb) if status_cb else None,
873             errptr)
874
875         if self._callback_excinfo:
876             gpgme.gpg_raise_callback_exception(self)
877
878         errorcheck(err)
879
880         status = gpgme.gpgme_error_t_p_value(errptr)
881         gpgme.delete_gpgme_error_t_p(errptr)
882
883         return GPGMEError(status) if status != 0 else None
884
885     def interact(self, key, func, sink=None, flags=0, fnc_value=None):
886         """Interact with the engine
887
888         This method can be used to edit keys and cards interactively.
889         KEY is the key to edit, FUNC is called repeatedly with two
890         unicode arguments, 'keyword' and 'args'.  See the GPGME manual
891         for details.
892
893         Keyword arguments:
894         sink            -- if given, additional output is written here
895         flags           -- use constants.INTERACT_CARD to edit a card
896
897         Raises:
898         GPGMEError      -- as signaled by the underlying library
899
900         """
901         if key is None:
902             raise ValueError("First argument cannot be None")
903
904         if sink is None:
905             sink = Data()
906
907         if fnc_value:
908             opaquedata = (weakref.ref(self), func, fnc_value)
909         else:
910             opaquedata = (weakref.ref(self), func)
911
912         result = gpgme.gpgme_op_interact(self.wrapped, key, flags,
913                                          opaquedata, sink)
914         if self._callback_excinfo:
915             gpgme.gpg_raise_callback_exception(self)
916         errorcheck(result)
917
918     @property
919     def signers(self):
920         """Keys used for signing"""
921         return [self.signers_enum(i) for i in range(self.signers_count())]
922
923     @signers.setter
924     def signers(self, signers):
925         old = self.signers
926         self.signers_clear()
927         try:
928             for key in signers:
929                 self.signers_add(key)
930         except:
931             self.signers = old
932             raise
933
934     @property
935     def pinentry_mode(self):
936         """Pinentry mode"""
937         return self.get_pinentry_mode()
938
939     @pinentry_mode.setter
940     def pinentry_mode(self, value):
941         self.set_pinentry_mode(value)
942
943     @property
944     def protocol(self):
945         """Protocol to use"""
946         return self.get_protocol()
947
948     @protocol.setter
949     def protocol(self, value):
950         errorcheck(gpgme.gpgme_engine_check_version(value))
951         self.set_protocol(value)
952
953     @property
954     def home_dir(self):
955         """Engine's home directory"""
956         return self.engine_info.home_dir
957
958     @home_dir.setter
959     def home_dir(self, value):
960         self.set_engine_info(self.protocol, home_dir=value)
961
962     _ctype = 'gpgme_ctx_t'
963     _cprefix = 'gpgme_'
964
965     def _errorcheck(self, name):
966         """This function should list all functions returning gpgme_error_t"""
967         # The list of functions is created using:
968         #
969         # $ grep '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \
970         # | grep -v _op_ | awk "/\(gpgme_ctx/ { printf (\"'%s',\\n\", \$2) } "
971         return ((name.startswith('gpgme_op_') and not
972             name.endswith('_result')) or name in {'gpgme_new',
973             'gpgme_set_ctx_flag', 'gpgme_set_protocol',
974             'gpgme_set_sub_protocol', 'gpgme_set_keylist_mode',
975             'gpgme_set_pinentry_mode', 'gpgme_set_locale',
976             'gpgme_ctx_set_engine_info', 'gpgme_signers_add',
977             'gpgme_sig_notation_add', 'gpgme_set_sender', 'gpgme_cancel',
978             'gpgme_cancel_async', 'gpgme_get_key'})
979
980     _boolean_properties = {'armor', 'textmode', 'offline'}
981
982     def __del__(self):
983         if not gpgme:
984             # At interpreter shutdown, gpgme is set to NONE.
985             return
986
987         self._free_passcb()
988         self._free_progresscb()
989         self._free_statuscb()
990         if self.own and self.wrapped and gpgme.gpgme_release:
991             gpgme.gpgme_release(self.wrapped)
992             self.wrapped = None
993
994     # Implement the context manager protocol.
995     def __enter__(self):
996         return self
997
998     def __exit__(self, type, value, tb):
999         self.__del__()
1000
1001     def op_keylist_all(self, *args, **kwargs):
1002         self.op_keylist_start(*args, **kwargs)
1003         key = self.op_keylist_next()
1004         while key:
1005             yield key
1006             key = self.op_keylist_next()
1007         self.op_keylist_end()
1008
1009     def op_keylist_next(self):
1010         """Returns the next key in the list created
1011         by a call to op_keylist_start().  The object returned
1012         is of type Key."""
1013         ptr = gpgme.new_gpgme_key_t_p()
1014         try:
1015             errorcheck(gpgme.gpgme_op_keylist_next(self.wrapped, ptr))
1016             key = gpgme.gpgme_key_t_p_value(ptr)
1017         except errors.GPGMEError as excp:
1018             key = None
1019             if excp.getcode() != errors.EOF:
1020                 raise excp
1021         gpgme.delete_gpgme_key_t_p(ptr)
1022         if key:
1023             key.__del__ = lambda self: gpgme.gpgme_key_unref(self)
1024             return key
1025
1026     def get_key(self, fpr, secret=False):
1027         """Get a key given a fingerprint
1028
1029         Keyword arguments:
1030         secret          -- to request a secret key
1031
1032         Returns:
1033                         -- the matching key
1034
1035         Raises:
1036         KeyError        -- if the key was not found
1037         GPGMEError      -- as signaled by the underlying library
1038
1039         """
1040         ptr = gpgme.new_gpgme_key_t_p()
1041
1042         try:
1043             errorcheck(gpgme.gpgme_get_key(self.wrapped, fpr, ptr, secret))
1044         except errors.GPGMEError as e:
1045             if e.getcode() == errors.EOF:
1046                 raise errors.KeyNotFound(fpr)
1047             raise e
1048
1049         key = gpgme.gpgme_key_t_p_value(ptr)
1050         gpgme.delete_gpgme_key_t_p(ptr)
1051         assert key
1052         key.__del__ = lambda self: gpgme.gpgme_key_unref(self)
1053         return key
1054
1055     def op_trustlist_all(self, *args, **kwargs):
1056         self.op_trustlist_start(*args, **kwargs)
1057         trust = self.op_trustlist_next()
1058         while trust:
1059             yield trust
1060             trust = self.op_trustlist_next()
1061         self.op_trustlist_end()
1062
1063     def op_trustlist_next(self):
1064         """Returns the next trust item in the list created
1065         by a call to op_trustlist_start().  The object returned
1066         is of type TrustItem."""
1067         ptr = gpgme.new_gpgme_trust_item_t_p()
1068         try:
1069             errorcheck(gpgme.gpgme_op_trustlist_next(self.wrapped, ptr))
1070             trust = gpgme.gpgme_trust_item_t_p_value(ptr)
1071         except errors.GPGMEError as excp:
1072             trust = None
1073             if excp.getcode() != errors.EOF:
1074                 raise
1075         gpgme.delete_gpgme_trust_item_t_p(ptr)
1076         return trust
1077
1078     def set_passphrase_cb(self, func, hook=None):
1079         """Sets the passphrase callback to the function specified by func.
1080
1081         When the system needs a passphrase, it will call func with three args:
1082         hint, a string describing the key it needs the passphrase for;
1083         desc, a string describing the passphrase it needs;
1084         prev_bad, a boolean equal True if this is a call made after
1085         unsuccessful previous attempt.
1086
1087         If hook has a value other than None it will be passed into the func
1088         as a forth argument.
1089
1090         Please see the GPGME manual for more information.
1091         """
1092         if func is None:
1093             hookdata = None
1094         else:
1095             if hook is None:
1096                 hookdata = (weakref.ref(self), func)
1097             else:
1098                 hookdata = (weakref.ref(self), func, hook)
1099         gpgme.gpg_set_passphrase_cb(self, hookdata)
1100
1101     def _free_passcb(self):
1102         if gpgme.gpg_set_passphrase_cb:
1103             self.set_passphrase_cb(None)
1104
1105     def set_progress_cb(self, func, hook=None):
1106         """Sets the progress meter callback to the function specified by FUNC.
1107         If FUNC is None, the callback will be cleared.
1108
1109         This function will be called to provide an interactive update
1110         of the system's progress.  The function will be called with
1111         three arguments, type, total, and current.  If HOOK is not
1112         None, it will be supplied as fourth argument.
1113
1114         Please see the GPGME manual for more information.
1115
1116         """
1117         if func is None:
1118             hookdata = None
1119         else:
1120             if hook is None:
1121                 hookdata = (weakref.ref(self), func)
1122             else:
1123                 hookdata = (weakref.ref(self), func, hook)
1124         gpgme.gpg_set_progress_cb(self, hookdata)
1125
1126     def _free_progresscb(self):
1127         if gpgme.gpg_set_progress_cb:
1128             self.set_progress_cb(None)
1129
1130     def set_status_cb(self, func, hook=None):
1131         """Sets the status callback to the function specified by FUNC.  If
1132         FUNC is None, the callback will be cleared.
1133
1134         The function will be called with two arguments, keyword and
1135         args.  If HOOK is not None, it will be supplied as third
1136         argument.
1137
1138         Please see the GPGME manual for more information.
1139
1140         """
1141         if func is None:
1142             hookdata = None
1143         else:
1144             if hook is None:
1145                 hookdata = (weakref.ref(self), func)
1146             else:
1147                 hookdata = (weakref.ref(self), func, hook)
1148         gpgme.gpg_set_status_cb(self, hookdata)
1149
1150     def _free_statuscb(self):
1151         if gpgme.gpg_set_status_cb:
1152             self.set_status_cb(None)
1153
1154     @property
1155     def engine_info(self):
1156         """Configuration of the engine currently in use"""
1157         p = self.protocol
1158         infos = [i for i in self.get_engine_info() if i.protocol == p]
1159         assert len(infos) == 1
1160         return infos[0]
1161
1162     def get_engine_info(self):
1163         """Get engine configuration
1164
1165         Returns information about all configured and installed
1166         engines.
1167
1168         Returns:
1169         infos           -- a list of engine infos
1170
1171         """
1172         return gpgme.gpgme_ctx_get_engine_info(self.wrapped)
1173
1174     def set_engine_info(self, proto, file_name=None, home_dir=None):
1175         """Change engine configuration
1176
1177         Changes the configuration of the crypto engine implementing
1178         the protocol 'proto' for the context.
1179
1180         Keyword arguments:
1181         file_name       -- engine program file name (unchanged if None)
1182         home_dir        -- configuration directory (unchanged if None)
1183
1184         """
1185         self.ctx_set_engine_info(proto, file_name, home_dir)
1186
1187     def wait(self, hang):
1188         """Wait for asynchronous call to finish. Wait forever if hang is True.
1189         Raises an exception on errors.
1190
1191         Please read the GPGME manual for more information.
1192
1193         """
1194         ptr = gpgme.new_gpgme_error_t_p()
1195         gpgme.gpgme_wait(self.wrapped, ptr, hang)
1196         status = gpgme.gpgme_error_t_p_value(ptr)
1197         gpgme.delete_gpgme_error_t_p(ptr)
1198         errorcheck(status)
1199
1200     def op_edit(self, key, func, fnc_value, out):
1201         """Start key editing using supplied callback function
1202
1203         Note: This interface is deprecated and will be removed with
1204         GPGME 1.8.  Please use .interact instead.  Furthermore, we
1205         implement this using gpgme_op_interact, so callbacks will get
1206         called with string keywords instead of numeric status
1207         messages.  Code that is using constants.STATUS_X or
1208         constants.status.X will continue to work, whereas code using
1209         magic numbers will break as a result.
1210
1211         """
1212         warnings.warn("Call to deprecated method op_edit.",
1213                       category=DeprecationWarning)
1214         return self.interact(key, func, sink=out, fnc_value=fnc_value)
1215
1216
1217 class Data(GpgmeWrapper):
1218     """Data buffer
1219
1220     A lot of data has to be exchanged between the user and the crypto
1221     engine, like plaintext messages, ciphertext, signatures and
1222     information about the keys.  The technical details about
1223     exchanging the data information are completely abstracted by
1224     GPGME.  The user provides and receives the data via `gpgme_data_t'
1225     objects, regardless of the communication protocol between GPGME
1226     and the crypto engine in use.
1227
1228     This Data class is the implementation of the GpgmeData objects.
1229
1230     Please see the information about __init__ for instantiation.
1231
1232     """
1233
1234     _ctype = 'gpgme_data_t'
1235     _cprefix = 'gpgme_data_'
1236
1237     def _errorcheck(self, name):
1238         """This function should list all functions returning gpgme_error_t"""
1239         # This list is compiled using
1240         #
1241         # $ grep -v '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \
1242         #   | awk "/\(gpgme_data_t/ { printf (\"'%s',\\n\", \$2) } " \
1243         #   | sed "s/'\\*/'/"
1244         return name not in {
1245             'gpgme_data_read',
1246             'gpgme_data_write',
1247             'gpgme_data_seek',
1248             'gpgme_data_release',
1249             'gpgme_data_release_and_get_mem',
1250             'gpgme_data_get_encoding',
1251             'gpgme_data_get_file_name',
1252             'gpgme_data_identify',
1253         }
1254
1255     def __init__(self, string=None, file=None, offset=None,
1256                  length=None, cbs=None, copy=True):
1257         """Initialize a new gpgme_data_t object.
1258
1259         If no args are specified, make it an empty object.
1260
1261         If string alone is specified, initialize it with the data
1262         contained there.
1263
1264         If file, offset, and length are all specified, file must
1265         be either a filename or a file-like object, and the object
1266         will be initialized by reading the specified chunk from the file.
1267
1268         If cbs is specified, it MUST be a tuple of the form:
1269
1270         (read_cb, write_cb, seek_cb, release_cb[, hook])
1271
1272         where the first four items are functions implementing reading,
1273         writing, seeking the data, and releasing any resources once
1274         the data object is deallocated.  The functions must match the
1275         following prototypes:
1276
1277             def read(amount, hook=None):
1278                 return <a b"bytes" object>
1279
1280             def write(data, hook=None):
1281                 return <the number of bytes written>
1282
1283             def seek(offset, whence, hook=None):
1284                 return <the new file position>
1285
1286             def release(hook=None):
1287                 <return value and exceptions are ignored>
1288
1289         The functions may be bound methods.  In that case, you can
1290         simply use the 'self' reference instead of using a hook.
1291
1292         If file is specified without any other arguments, then
1293         it must be a filename, and the object will be initialized from
1294         that file.
1295
1296         """
1297         super(Data, self).__init__(None)
1298         self.data_cbs = None
1299
1300         if cbs is not None:
1301             self.new_from_cbs(*cbs)
1302         elif string is not None:
1303             self.new_from_mem(string, copy)
1304         elif file is not None and offset is not None and length is not None:
1305             self.new_from_filepart(file, offset, length)
1306         elif file is not None:
1307             if util.is_a_string(file):
1308                 self.new_from_file(file, copy)
1309             else:
1310                 self.new_from_fd(file)
1311         else:
1312             self.new()
1313
1314     def __del__(self):
1315         if not gpgme:
1316             # At interpreter shutdown, gpgme is set to NONE.
1317             return
1318
1319         if self.wrapped is not None and gpgme.gpgme_data_release:
1320             gpgme.gpgme_data_release(self.wrapped)
1321             if self._callback_excinfo:
1322                 gpgme.gpg_raise_callback_exception(self)
1323             self.wrapped = None
1324         self._free_datacbs()
1325
1326     # Implement the context manager protocol.
1327     def __enter__(self):
1328         return self
1329
1330     def __exit__(self, type, value, tb):
1331         self.__del__()
1332
1333     def _free_datacbs(self):
1334         self._data_cbs = None
1335
1336     def new(self):
1337         tmp = gpgme.new_gpgme_data_t_p()
1338         errorcheck(gpgme.gpgme_data_new(tmp))
1339         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
1340         gpgme.delete_gpgme_data_t_p(tmp)
1341
1342     def new_from_mem(self, string, copy=True):
1343         tmp = gpgme.new_gpgme_data_t_p()
1344         errorcheck(gpgme.gpgme_data_new_from_mem(tmp, string, len(string),
1345                                                  copy))
1346         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
1347         gpgme.delete_gpgme_data_t_p(tmp)
1348
1349     def new_from_file(self, filename, copy=True):
1350         tmp = gpgme.new_gpgme_data_t_p()
1351         try:
1352             errorcheck(gpgme.gpgme_data_new_from_file(tmp, filename, copy))
1353         except errors.GPGMEError as e:
1354             if e.getcode() == errors.INV_VALUE and not copy:
1355                 raise ValueError("delayed reads are not yet supported")
1356             else:
1357                 raise e
1358         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
1359         gpgme.delete_gpgme_data_t_p(tmp)
1360
1361     def new_from_cbs(self, read_cb, write_cb, seek_cb, release_cb, hook=None):
1362         tmp = gpgme.new_gpgme_data_t_p()
1363         if hook is not None:
1364             hookdata = (weakref.ref(self),
1365                         read_cb, write_cb, seek_cb, release_cb, hook)
1366         else:
1367             hookdata = (weakref.ref(self),
1368                         read_cb, write_cb, seek_cb, release_cb)
1369         gpgme.gpg_data_new_from_cbs(self, hookdata, tmp)
1370         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
1371         gpgme.delete_gpgme_data_t_p(tmp)
1372
1373     def new_from_filepart(self, file, offset, length):
1374         """This wraps the GPGME gpgme_data_new_from_filepart() function.
1375         The argument "file" may be:
1376
1377         * a string specifying a file name, or
1378         * a file-like object supporting the fileno() and the mode attribute.
1379
1380         """
1381
1382         tmp = gpgme.new_gpgme_data_t_p()
1383         filename = None
1384         fp = None
1385
1386         if util.is_a_string(file):
1387             filename = file
1388         else:
1389             fp = gpgme.fdopen(file.fileno(), file.mode)
1390             if fp is None:
1391                 raise ValueError("Failed to open file from %s arg %s" %
1392                                  (str(type(file)), str(file)))
1393
1394         errorcheck(gpgme.gpgme_data_new_from_filepart(tmp, filename, fp,
1395                                                       offset, length))
1396         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
1397         gpgme.delete_gpgme_data_t_p(tmp)
1398
1399     def new_from_fd(self, file):
1400         """This wraps the GPGME gpgme_data_new_from_fd() function.  The
1401         argument "file" must be a file-like object, supporting the
1402         fileno() method.
1403
1404         """
1405         tmp = gpgme.new_gpgme_data_t_p()
1406         errorcheck(gpgme.gpgme_data_new_from_fd(tmp, file.fileno()))
1407         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
1408         gpgme.delete_gpgme_data_t_p(tmp)
1409
1410     def new_from_stream(self, file):
1411         """This wrap around gpgme_data_new_from_stream is an alias for
1412         new_from_fd() method since in python there's not difference
1413         between file stream and file descriptor"""
1414         self.new_from_fd(file)
1415
1416     def write(self, buffer):
1417         """Write buffer given as string or bytes.
1418
1419         If a string is given, it is implicitly encoded using UTF-8."""
1420         written = gpgme.gpgme_data_write(self.wrapped, buffer)
1421         if written < 0:
1422             if self._callback_excinfo:
1423                 gpgme.gpg_raise_callback_exception(self)
1424             else:
1425                 raise GPGMEError.fromSyserror()
1426         return written
1427
1428     def read(self, size=-1):
1429         """Read at most size bytes, returned as bytes.
1430
1431         If the size argument is negative or omitted, read until EOF is reached.
1432
1433         Returns the data read, or the empty string if there was no data
1434         to read before EOF was reached."""
1435
1436         if size == 0:
1437             return ''
1438
1439         if size > 0:
1440             try:
1441                 result = gpgme.gpgme_data_read(self.wrapped, size)
1442             except:
1443                 if self._callback_excinfo:
1444                     gpgme.gpg_raise_callback_exception(self)
1445                 else:
1446                     raise
1447             return result
1448         else:
1449             chunks = []
1450             while True:
1451                 try:
1452                     result = gpgme.gpgme_data_read(self.wrapped, 4096)
1453                 except:
1454                     if self._callback_excinfo:
1455                         gpgme.gpg_raise_callback_exception(self)
1456                     else:
1457                         raise
1458                 if len(result) == 0:
1459                     break
1460                 chunks.append(result)
1461             return b''.join(chunks)
1462
1463
1464 def pubkey_algo_string(subkey):
1465     """Return short algorithm string
1466
1467     Return a public key algorithm string (e.g. "rsa2048") for a given
1468     SUBKEY.
1469
1470     Returns:
1471     algo      - a string
1472
1473     """
1474     return gpgme.gpgme_pubkey_algo_string(subkey)
1475
1476
1477 def pubkey_algo_name(algo):
1478     """Return name of public key algorithm
1479
1480     Return the name of the public key algorithm for a given numeric
1481     algorithm id ALGO (cf. RFC4880).
1482
1483     Returns:
1484     algo      - a string
1485
1486     """
1487     return gpgme.gpgme_pubkey_algo_name(algo)
1488
1489
1490 def hash_algo_name(algo):
1491     """Return name of hash algorithm
1492
1493     Return the name of the hash algorithm for a given numeric
1494     algorithm id ALGO (cf. RFC4880).
1495
1496     Returns:
1497     algo      - a string
1498
1499     """
1500     return gpgme.gpgme_hash_algo_name(algo)
1501
1502
1503 def get_protocol_name(proto):
1504     """Get protocol description
1505
1506     Get the string describing protocol PROTO.
1507
1508     Returns:
1509     proto     - a string
1510
1511     """
1512     return gpgme.gpgme_get_protocol_name(proto)
1513
1514
1515 def addrspec_from_uid(uid):
1516     """Return the address spec
1517
1518     Return the addr-spec (cf. RFC2822 section 4.3) from a user id UID.
1519
1520     Returns:
1521     addr_spec - a string
1522
1523     """
1524     return gpgme.gpgme_addrspec_from_uid(uid)
1525
1526
1527 def check_version(version=None):
1528     return gpgme.gpgme_check_version(version)
1529
1530 # check_version also makes sure that several subsystems are properly
1531 # initialized, and it must be run at least once before invoking any
1532 # other function.  We do it here so that the user does not have to do
1533 # it unless she really wants to check for a certain version.
1534 check_version()
1535
1536
1537 def engine_check_version(proto):
1538     try:
1539         errorcheck(gpgme.gpgme_engine_check_version(proto))
1540         return True
1541     except errors.GPGMEError:
1542         return False
1543
1544
1545 def get_engine_info():
1546     ptr = gpgme.new_gpgme_engine_info_t_p()
1547     try:
1548         errorcheck(gpgme.gpgme_get_engine_info(ptr))
1549         info = gpgme.gpgme_engine_info_t_p_value(ptr)
1550     except errors.GPGMEError:
1551         info = None
1552     gpgme.delete_gpgme_engine_info_t_p(ptr)
1553     return info
1554
1555
1556 def set_engine_info(proto, file_name, home_dir=None):
1557     """Changes the default configuration of the crypto engine implementing
1558     the protocol 'proto'. 'file_name' is the file name of
1559     the executable program implementing this protocol. 'home_dir' is the
1560     directory name of the configuration directory (engine's default is
1561     used if omitted)."""
1562     errorcheck(gpgme.gpgme_set_engine_info(proto, file_name, home_dir))
1563
1564
1565 def set_locale(category, value):
1566     """Sets the default locale used by contexts"""
1567     errorcheck(gpgme.gpgme_set_locale(None, category, value))
1568
1569
1570 def wait(hang):
1571     """Wait for asynchronous call on any Context  to finish.
1572     Wait forever if hang is True.
1573
1574     For finished anynch calls it returns a tuple (status, context):
1575         status  - status return by asnynchronous call.
1576         context - context which caused this call to return.
1577
1578     Please read the GPGME manual of more information."""
1579     ptr = gpgme.new_gpgme_error_t_p()
1580     context = gpgme.gpgme_wait(None, ptr, hang)
1581     status = gpgme.gpgme_error_t_p_value(ptr)
1582     gpgme.delete_gpgme_error_t_p(ptr)
1583     if context is None:
1584         errorcheck(status)
1585     else:
1586         context = Context(context)
1587     return (status, context)