1
2
3
4 """
5 Overview
6 ========
7
8 The ``grizzled.forwarder`` module contain classes that make building proxies
9 easier.
10 """
11
12 from __future__ import absolute_import
13
14 __docformat__ = "restructuredtext en"
15
16
17
18
19
20 import logging
21 from types import MethodType
22
23
24
25
26
27 __all__ = ['Forwarder']
28
29
30
31
32
33
34
35
36
37 log = logging.getLogger('grizzled.proxy')
38
39
40
41
42
44 """
45 The ``grizzled.forwarder.Forwarder`` class is intended to be used as
46 a mixin, to make it easier for classes to forward calls to another
47 class. The mix ``Forwarder`` into a class, simply include it as
48 one of the base classes.
49
50 **WARNING**: ``Forwarder`` intercepts calls to ``__getattr__``, so
51 don't mix it in if your class is already overriding ``__getattr__``.
52
53 Examples
54 --------
55
56 Forward all unimplemented methods to a file:
57
58 .. python::
59
60 from grizzled.forwarder import Forwarder
61
62 class MyFileWrapper(Forwarder):
63 def __init__(self, file):
64 Forwarder.__init__(self, file)
65
66 w = MyFileWrapper(open('/tmp/foo'))
67 for line in w.readlines():
68 print line
69
70 Forward all unimplemented calls, *except* ``name``, to the specified
71 object. Calls to ``name`` will raise an ``AttributeError``:
72
73
74 .. python::
75
76 from grizzled.forwarder import Forwarder
77
78 class MyFileWrapper(Forwarder):
79 def __init__(self, file):
80 Forwarder.__init__(self, file, 'name')
81 """
82
83 - def __init__(self, wrapped, *exceptions):
84 """
85 Initialize a new ``Forwarder`` that will pass unimplemented calls
86 (method calls, attribute accesses, etc.) to the specified object.
87
88 :Parameters:
89 wrapped : object
90 the object to which to pass unknown attributes
91 exceptions : str
92 one or more names (as separate arguments) of methods
93 that should not be intercepted (and will, therefore,
94 result in ``AttributeError`` exceptions if invoked,
95 absent any other intervention).
96 """
97 self._wrapped = wrapped
98 self._exceptions = [e for e in exceptions[0]]
99
101
102
103 obj = self.__getattribute__('_wrapped')
104 exceptions = self.__getattribute__('_exceptions')
105 if (obj is None) or (name in exceptions):
106 self.__getattribute__(name)
107
108 else:
109 try:
110 attr = getattr(obj, name)
111 if isinstance(obj, MethodType):
112 return new.instancemethod(attr.im_func, self, obj.__class__)
113 else:
114 return attr
115 except AttributeError:
116
117 raise AttributeError("'%s' object has no attribute '%s'" %
118 (self.__class__.__name__, name))
119