e6e89689e633d34009e896920efae7df6dfd7c20
[gpgme.git] / lang / python / pyme / results.py
1 # Robust result objects
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 Lesser General Public License as
9 # published by the Free Software Foundation; either version 2.1 of the
10 # License, or (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 """Robust result objects
21
22 Results returned by the underlying library are fragile, i.e. they are
23 only valid until the next operation is performed in the context.
24
25 We cannot arbitrarily constrain the lifetime of Python objects, we
26 therefore create deep copies of the results.
27
28 """
29
30 class Result(object):
31     """Result object
32
33     Describes the result of an operation.
34
35     """
36
37     """Convert to types"""
38     _type = {}
39
40     """Map functions over list attributes"""
41     _map = {}
42
43     """Automatically copy unless blacklisted"""
44     _blacklist = {
45         'acquire', 'append', 'disown', 'next', 'own', 'this', 'thisown',
46     }
47     def __init__(self, fragile):
48         for key, func in self._type.items():
49             setattr(self, key, func(getattr(fragile, key)))
50
51         for key, func in self._map.items():
52             setattr(self, key, list(map(func, getattr(fragile, key))))
53
54         for key, func in self._map.items():
55             setattr(self, key, list(map(func, getattr(fragile, key))))
56
57         for key in dir(fragile):
58             if key.startswith('_') or key in self._blacklist:
59                 continue
60             if hasattr(self, key):
61                 continue
62
63             setattr(self, key, getattr(fragile, key))
64
65     def __str__(self):
66         return '<{} {}>'.format(
67             self.__class__.__name__,
68             ', '.join('{}: {}'.format(k, getattr(self, k))
69                       for k in dir(self) if not k.startswith('_')))
70
71 class InvalidKey(Result):
72     pass
73
74 class EncryptResult(Result):
75     _map = dict(invalid_recipients=InvalidKey)
76
77 class Recipient(Result):
78     pass
79
80 class DecryptResult(Result):
81     _type = dict(wrong_key_usage=bool)
82     _map = dict(recipients=Recipient)
83
84 class NewSignature(Result):
85     pass
86
87 class SignResult(Result):
88     _map = dict(invalid_signers=InvalidKey, signatures=NewSignature)
89
90 class Notation(Result):
91     pass
92
93 class TofuInfo(Result):
94     pass
95
96 class Signature(Result):
97     _type = dict(wrong_key_usage=bool, chain_model=bool)
98     _map = dict(notations=Notation, tofu=TofuInfo)
99
100 class VerifyResult(Result):
101     _map = dict(signatures=Signature)
102
103 class ImportStatus(Result):
104     pass
105
106 class ImportResult(Result):
107     _map = dict(imports=ImportStatus)
108
109 class GenkeyResult(Result):
110     _type = dict(primary=bool, sub=bool)
111
112 class KeylistResult(Result):
113     _type = dict(truncated=bool)
114
115 class VFSMountResult(Result):
116     pass