1 """Base classes for descriptors and descriptor owners.
2
3 @bug: L{Proxy} is currently unaware of its context.
4 @author: Stephan Wenger
5 @date: 2012-02-29
6 """
7
8 from inspect import getmembers as _getmembers
9 import types as _types
10 import numpy as _np
11
12 import glitter.raw as _gl
13 from glitter.utils.dtypes import coerce_array, int32
14 from glitter.utils.objects import with_obj
15
17 - def __init__(self, getter=None, get_args=(), setter=None, set_args=(), dtype=None, shape=(), enum=None, name=None):
18 self._getter = getter
19 self._get_args = get_args
20 self._setter = setter
21 self._set_args = set_args
22 self._dtype = dtype if dtype else int32
23 self._shape = None if shape is None else tuple(shape) if hasattr(shape, "__iter__") else (shape,)
24 self._enum = enum
25 self._name = name
26
28 _value = _np.empty(self._shape, dtype=self._dtype.as_numpy())
29 args = list(self._get_args) + [_gl.cast(_value.ctypes, self._getter.argtypes[-1])]
30 with obj:
31 self._getter(*args)
32 value = _value.item() if _value.shape is () else _value
33 if self._enum is not None:
34 if hasattr(value, "__iter__"):
35 value = [self._enum[x] for x in value]
36 else:
37 value = self._enum[value]
38 return value
39
41 if self._setter is None:
42 raise AttributeError("can't set attribute")
43 if self._enum is not None:
44 if hasattr(value, "__iter__"):
45 _value = [self._enum(x)._value for x in value]
46 else:
47 _value = self._enum(value)._value
48 else:
49 _value = value
50 _value = coerce_array(_value, dtype=self._dtype)
51 if len(self._set_args) + len(_value) == len(self._setter.argtypes):
52 args = list(self._set_args) + (list(_value) if _value.ndim == 1 else [x.ctypes for x in _value])
53 elif len(self._set_args) + 1 == len(self._setter.argtypes):
54 args = list(self._set_args) + [_value.ctypes]
55 else:
56 raise RuntimeError("no valid setter invocation found")
57 with obj:
58 self._setter(*args)
59
61 if self._name:
62 return "proxy for %s" % self._name
63 elif self._getter and self._setter:
64 return "proxy for %s(%s) / %s(%s)" % (
65 self._getter.__name__, ", ".join(map(str, self._get_args)),
66 self._setter.__name__, ", ".join(map(str, self._set_args)))
67 elif self._getter:
68 return "proxy for %s(%s)" % (self._getter.__name__, ", ".join(map(str, self._get_args)))
69 elif self._setter:
70 return "proxy for %s(%s)" % (self._setter.__name__, ", ".join(map(str, self._set_args)))
71 else:
72 return "proxy object"
73
75 - def __init__(self, lst, insert_callback=None, delete_callback=None):
76 self._lst = lst
77 self._insert_callback = insert_callback
78 self._delete_callback = delete_callback
79
81 self._lst.append(x)
82 self._insert_callback(x)
83
85 for x in xs:
86 self.append(x)
87
89 self._lst.remove(x)
90 self._delete_callback(x)
91
94
97
100
102 """Mixin to enable runtime-added descriptors."""
103
110
117
120 self._obj = obj
121 self._name = name
122
124 return getattr(self._obj, self._name)
125
127 setattr(self._obj, self._name, value)
128
130 delattr(self._obj, self._name)
131
134 self._obj = obj
135 self._idx = idx
136
138 return self._obj[self._idx]
139
141 self._obj[self._idx] = value
142
144 del self._obj[self._idx]
145
147 """Add proxies for methods and properties of C{obj} to C{parent}."""
148
149
150 for key, value in _getmembers(obj):
151 if key.startswith("_"):
152 continue
153 if isinstance(value, (_types.FunctionType, _types.MethodType)):
154 setattr(parent, key, with_obj(parent, value))
155
156
157 for key, value in _getmembers(type(obj)):
158 if key.startswith("_"):
159 continue
160 if hasattr(value, "__get__") and not callable(value):
161 setattr(parent, key, PropertyProxy(obj, key))
162
163
164 if isinstance(obj, InstanceDescriptorMixin):
165 for key, value in obj.__dict__.items():
166 if key.startswith("_"):
167 continue
168 if hasattr(value, "__get__"):
169 setattr(parent, key, PropertyProxy(obj, key))
170
171 __all__ = ["Proxy", "ListProxy", "InstanceDescriptorMixin", "PropertyProxy", "ItemProxy", "add_proxies"]
172