Package glitter :: Package utils :: Module proxy
[hide private]
[frames] | no frames]

Source Code for Module glitter.utils.proxy

  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   
16 -class Proxy(object):
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
27 - def __get__(self, obj, cls):
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
40 - def __set__(self, obj, value):
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
60 - def __repr__(self):
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
74 -class ListProxy(object):
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
80 - def append(self, x):
81 self._lst.append(x) 82 self._insert_callback(x)
83
84 - def extend(self, xs):
85 for x in xs: 86 self.append(x)
87
88 - def remove(self, x):
89 self._lst.remove(x) 90 self._delete_callback(x)
91
92 - def __iadd__(self, xs):
93 self.extend(xs)
94
95 - def __getitem__(self, key):
96 return self._lst[key]
97
98 - def __len__(self):
99 return len(self._lst)
100
101 -class InstanceDescriptorMixin(object):
102 """Mixin to enable runtime-added descriptors.""" 103
104 - def __getattribute__(self, name):
105 attr = super(InstanceDescriptorMixin, self).__getattribute__(name) 106 if hasattr(attr, "__get__") and not callable(attr): 107 return attr.__get__(self, self.__class__) 108 else: 109 return attr
110
111 - def __setattr__(self, name, value):
112 try: 113 attr = super(InstanceDescriptorMixin, self).__getattribute__(name) 114 return attr.__set__(self, value) 115 except AttributeError: 116 return super(InstanceDescriptorMixin, self).__setattr__(name, value)
117
118 -class PropertyProxy(object):
119 - def __init__(self, obj, name):
120 self._obj = obj 121 self._name = name
122
123 - def __get__(self, obj, cls):
124 return getattr(self._obj, self._name)
125
126 - def __set__(self, obj, value):
127 setattr(self._obj, self._name, value)
128
129 - def __delete__(self, obj):
130 delattr(self._obj, self._name)
131
132 -class ItemProxy(object):
133 - def __init__(self, obj, idx):
134 self._obj = obj 135 self._idx = idx
136
137 - def __get__(self, obj, cls):
138 return self._obj[self._idx]
139
140 - def __set__(self, obj, value):
141 self._obj[self._idx] = value
142
143 - def __delete__(self, obj):
144 del self._obj[self._idx]
145
146 -def add_proxies(parent, obj):
147 """Add proxies for methods and properties of C{obj} to C{parent}.""" 148 149 # add functions and methods 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 # add properties and other descriptors (can be accessed via the class only) 157 for key, value in _getmembers(type(obj)): 158 if key.startswith("_"): 159 continue 160 if hasattr(value, "__get__") and not callable(value): # exclude member functions 161 setattr(parent, key, PropertyProxy(obj, key)) 162 163 # add instance descriptors if applicable 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