python: Robust exception handling in callbacks.
[gpgme.git] / lang / python / pyme / util.py
1 # $Id$
2 # Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
3 # Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
4 #
5 #    This library is free software; you can redistribute it and/or
6 #    modify it under the terms of the GNU Lesser General Public
7 #    License as published by the Free Software Foundation; either
8 #    version 2.1 of the License, or (at your option) any later version.
9 #
10 #    This library is distributed in the hope that it will be useful,
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 #    Lesser General Public License for more details.
14 #
15 #    You should have received a copy of the GNU Lesser General Public
16 #    License along with this library; if not, write to the Free Software
17 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
18
19 from . import pygpgme
20 from .errors import errorcheck
21
22 def process_constants(starttext, dict):
23     """Called by the constant libraries to load up the appropriate constants
24     from the C library."""
25     index = len(starttext)
26     for identifier in dir(pygpgme):
27         if not identifier.startswith(starttext):
28             continue
29         name = identifier[index:]
30         dict[name] = getattr(pygpgme, identifier)
31
32 class GpgmeWrapper(object):
33     """Base class all Pyme wrappers for GPGME functionality.  Not to be
34     instantiated directly."""
35
36     def __init__(self, wrapped):
37         self._callback_excinfo = None
38         self.wrapped = wrapped
39
40     def __repr__(self):
41         return '<instance of %s.%s with GPG object at %s>' % \
42                (__name__, self.__class__.__name__,
43                 self.wrapped)
44
45     def __str__(self):
46         return repr(self)
47
48     def __hash__(self):
49         return hash(repr(self.wrapped))
50
51     def __eq__(self, other):
52         if other == None:
53             return False
54         else:
55             return repr(self.wrapped) == repr(other.wrapped)
56
57     def _getctype(self):
58         """Must be implemented by child classes.
59
60         Must return the name of the c type."""
61         raise NotImplementedError()
62
63     def _getnameprepend(self):
64         """Must be implemented by child classes.
65
66         Must return the prefix of all c functions mapped to methods of
67         this class."""
68         raise NotImplementedError()
69
70     def _errorcheck(self, name):
71         """Must be implemented by child classes.
72
73         This function must return a trueish value for all c functions
74         returning gpgme_error_t."""
75         raise NotImplementedError()
76
77     def __getattr__(self, key):
78         """On-the-fly function generation."""
79         if key[0] == '_' or self._getnameprepend() == None:
80             return None
81         name = self._getnameprepend() + key
82         func = getattr(pygpgme, name)
83
84         if self._errorcheck(name):
85             def _funcwrap(slf, *args, **kwargs):
86                 result = func(slf.wrapped, *args, **kwargs)
87                 if slf._callback_excinfo:
88                     pygpgme.pygpgme_raise_callback_exception(slf)
89                 return errorcheck(result, "Invocation of " + name)
90         else:
91             def _funcwrap(slf, *args, **kwargs):
92                 result = func(slf.wrapped, *args, **kwargs)
93                 if slf._callback_excinfo:
94                     pygpgme.pygpgme_raise_callback_exception(slf)
95                 return result
96
97         _funcwrap.__doc__ = getattr(func, "__doc__")
98
99         # Monkey-patch the class.
100         setattr(self.__class__, key, _funcwrap)
101
102         # Bind the method to 'self'.
103         def wrapper(*args, **kwargs):
104             return _funcwrap(self, *args, **kwargs)
105         _funcwrap.__doc__ = getattr(func, "__doc__")
106
107         return wrapper