1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 from __future__ import absolute_import
21
22 from cproton import pn_incref, pn_decref, \
23 pn_py2void, pn_void2py, \
24 pn_record_get, pn_record_def, pn_record_set, \
25 PN_PYREF
26
27 from ._exceptions import ProtonException
28
29
31
34
37
39 raise TypeError("does not support item assignment")
40
41
42 EMPTY_ATTRS = EmptyAttrs()
43
44
46 """ Wrapper for python objects that need to be stored in event contexts and be retrived again from them
47 Quick note on how this works:
48 The actual *python* object has only 3 attributes which redirect into the wrapped C objects:
49 _impl The wrapped C object itself
50 _attrs This is a special pn_record_t holding a PYCTX which is a python dict
51 every attribute in the python object is actually looked up here
52 _record This is the C record itself (so actually identical to _attrs really but
53 a different python type
54
55 Because the objects actual attributes are stored away they must be initialised *after* the wrapping
56 is set up. This is the purpose of the _init method in the wrapped object. Wrapper.__init__ will call
57 eht subclass _init to initialise attributes. So they *must not* be initialised in the subclass __init__
58 before calling the superclass (Wrapper) __init__ or they will not be accessible from the wrapper at all.
59
60 """
61
62 - def __init__(self, impl_or_constructor, get_context=None):
63 init = False
64 if callable(impl_or_constructor):
65
66 impl = impl_or_constructor()
67 if impl is None:
68 self.__dict__["_impl"] = impl
69 self.__dict__["_attrs"] = EMPTY_ATTRS
70 self.__dict__["_record"] = None
71 raise ProtonException(
72 "Wrapper failed to create wrapped object. Check for file descriptor or memory exhaustion.")
73 init = True
74 else:
75
76 impl = impl_or_constructor
77 pn_incref(impl)
78
79 if get_context:
80 record = get_context(impl)
81 attrs = pn_void2py(pn_record_get(record, PYCTX))
82 if attrs is None:
83 attrs = {}
84 pn_record_def(record, PYCTX, PN_PYREF)
85 pn_record_set(record, PYCTX, pn_py2void(attrs))
86 init = True
87 else:
88 attrs = EMPTY_ATTRS
89 init = False
90 record = None
91 self.__dict__["_impl"] = impl
92 self.__dict__["_attrs"] = attrs
93 self.__dict__["_record"] = record
94 if init: self._init()
95
97 attrs = self.__dict__["_attrs"]
98 if name in attrs:
99 return attrs[name]
100 else:
101 raise AttributeError(name + " not in _attrs")
102
104 if hasattr(self.__class__, name):
105 object.__setattr__(self, name, value)
106 else:
107 attrs = self.__dict__["_attrs"]
108 attrs[name] = value
109
111 attrs = self.__dict__["_attrs"]
112 if attrs:
113 del attrs[name]
114
116 return hash(addressof(self._impl))
117
119 if isinstance(other, Wrapper):
120 return addressof(self._impl) == addressof(other._impl)
121 return False
122
124 if isinstance(other, Wrapper):
125 return addressof(self._impl) != addressof(other._impl)
126 return True
127
129 pn_decref(self._impl)
130
132 return '<%s.%s 0x%x ~ 0x%x>' % (self.__class__.__module__,
133 self.__class__.__name__,
134 id(self), addressof(self._impl))
135
136
137 PYCTX = int(pn_py2void(Wrapper))
138 addressof = int
139