python: Fix skipping tests if running with GnuPG < 2.1.12.
[gpgme.git] / lang / python / tests / t-idiomatic.py
1 #!/usr/bin/env python
2
3 # Copyright (C) 2016 g10 Code GmbH
4 #
5 # This file is part of GPGME.
6 #
7 # GPGME is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # GPGME is distributed in the hope that it will be useful, but WITHOUT
13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
15 # Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this program; if not, see <http://www.gnu.org/licenses/>.
19
20 from __future__ import absolute_import, print_function, unicode_literals
21 del absolute_import, print_function, unicode_literals
22
23 import sys
24 import io
25 import os
26 import tempfile
27 import gpg
28 import support
29 _ = support # to appease pyflakes.
30
31 # Both Context and Data can be used as context manager:
32 with gpg.Context() as c, gpg.Data() as d:
33     c.get_engine_info()
34     d.write(b"Halloechen")
35     leak_c = c
36     leak_d = d
37 assert leak_c.wrapped == None
38 assert leak_d.wrapped == None
39
40 def sign_and_verify(source, signed, sink):
41     with gpg.Context() as c:
42         c.op_sign(source, signed, gpg.constants.sig.mode.NORMAL)
43         signed.seek(0, os.SEEK_SET)
44         c.op_verify(signed, None, sink)
45         result = c.op_verify_result()
46
47     assert len(result.signatures) == 1, "Unexpected number of signatures"
48     sig = result.signatures[0]
49     assert sig.summary == (gpg.constants.sigsum.VALID |
50                            gpg.constants.sigsum.GREEN)
51     assert gpg.errors.GPGMEError(sig.status).getcode() == gpg.errors.NO_ERROR
52
53     sink.seek(0, os.SEEK_SET)
54     assert sink.read() == b"Hallo Leute\n"
55
56 # Demonstrate automatic wrapping of file-like objects with 'fileno'
57 # method.
58 with tempfile.TemporaryFile() as source, \
59      tempfile.TemporaryFile() as signed, \
60      tempfile.TemporaryFile() as sink:
61     source.write(b"Hallo Leute\n")
62     source.seek(0, os.SEEK_SET)
63
64     sign_and_verify(source, signed, sink)
65
66 if sys.version_info[0] == 3:
67     # Python2's io.BytesIO does not implement the buffer interface,
68     # hence we cannot use it as sink.
69
70     # XXX: Python's io.BytesIo.truncate does not work as advertised.
71     # http://bugs.python.org/issue27261
72     bio = io.BytesIO()
73     bio.truncate(1)
74     if len(bio.getvalue()) != 1:
75         # This version of Python is affected, preallocate buffer.
76         preallocate = 128*b'\x00'
77     else:
78         preallocate = b''
79
80     # Demonstrate automatic wrapping of objects implementing the buffer
81     # interface, and the use of data objects with the 'with' statement.
82     with io.BytesIO(preallocate) as signed, gpg.Data() as sink:
83         sign_and_verify(b"Hallo Leute\n", signed, sink)