8f9d64529dd7384b74a0a356b7551c8b65bf89d1
[gpgme.git] / lang / python / tests / support.py
1 # Copyright (C) 2016 g10 Code GmbH
2 #
3 # This file is part of GPGME.
4 #
5 # GPGME is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # GPGME is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
13 # Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this program; if not, see <http://www.gnu.org/licenses/>.
17
18 from __future__ import absolute_import, print_function, unicode_literals
19 del absolute_import, print_function, unicode_literals
20
21 import contextlib
22 import shutil
23 import sys
24 import os
25 import tempfile
26 import time
27 import gpg
28
29 def assert_gpg_version(version=(2, 1, 0)):
30     with gpg.Context() as c:
31         if tuple(map(int, c.engine_info.version.split('.'))) < version:
32             print("GnuPG too old: have {0}, need {1}.".format(
33                 c.engine_info.version, '.'.join(version)))
34             sys.exit(77)
35
36 # known keys
37 alpha = "A0FF4590BB6122EDEF6E3C542D727CC768697734"
38 bob = "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2"
39 encrypt_only = "F52770D5C4DB41408D918C9F920572769B9FE19C"
40 sign_only = "7CCA20CCDE5394CEE71C9F0BFED153F12F18F45D"
41 no_such_key = "A" * 40
42
43 def make_filename(name):
44     return os.path.join(os.environ['top_srcdir'], 'tests', 'gpg', name)
45
46 def in_srcdir(name):
47     return os.path.join(os.environ['srcdir'], name)
48
49 verbose = int(os.environ.get('verbose', 0)) > 1
50 def print_data(data):
51     if verbose:
52         try:
53             # See if it is a file-like object.
54             data.seek(0, os.SEEK_SET)
55             data = data.read()
56         except:
57             # Hope for the best.
58             pass
59
60         if hasattr(sys.stdout, "buffer"):
61             sys.stdout.buffer.write(data)
62         else:
63             sys.stdout.write(data)
64
65 def mark_key_trusted(ctx, key):
66     class Editor(object):
67         def __init__(self):
68             self.steps = ["trust", "save"]
69         def edit(self, status, args, out):
70             if args == "keyedit.prompt":
71                 result = self.steps.pop(0)
72             elif args == "edit_ownertrust.value":
73                 result = "5"
74             elif args == "edit_ownertrust.set_ultimate.okay":
75                 result = "Y"
76             elif args == "keyedit.save.okay":
77                 result = "Y"
78             else:
79                 result = None
80             return result
81     with gpg.Data() as sink:
82         ctx.op_edit(key, Editor().edit, sink, sink)
83
84
85 # Python3.2 and up has tempfile.TemporaryDirectory, but we cannot use
86 # that, because there shutil.rmtree is used without
87 # ignore_errors=True, and that races against gpg-agent deleting its
88 # sockets.
89 class TemporaryDirectory(object):
90     def __enter__(self):
91         self.path = tempfile.mkdtemp()
92         return self.path
93     def __exit__(self, *args):
94         shutil.rmtree(self.path, ignore_errors=True)
95
96 @contextlib.contextmanager
97 def EphemeralContext():
98     with TemporaryDirectory() as tmp:
99         home = os.environ['GNUPGHOME']
100         shutil.copy(os.path.join(home, "gpg.conf"), tmp)
101         shutil.copy(os.path.join(home, "gpg-agent.conf"), tmp)
102
103         with gpg.Context(home_dir=tmp) as ctx:
104             yield ctx
105
106             # Ask the agent to quit.
107             agent_socket = os.path.join(tmp, "S.gpg-agent")
108             ctx.protocol = gpg.constants.protocol.ASSUAN
109             ctx.set_engine_info(ctx.protocol, file_name=agent_socket)
110             ctx.assuan_transact(["KILLAGENT"])
111
112             # Block until it is really gone.
113             while os.path.exists(agent_socket):
114                 time.sleep(.01)