Package pytilities :: Module attributecollectionbase
[hide private]
[frames] | no frames]

Source Code for Module pytilities.attributecollectionbase

  1  # Copyright (C) 2010 Tim Diels <limyreth@users.sourceforge.net> 
  2  #  
  3  # This file is part of pytilities. 
  4  #  
  5  # pytilities is free software: you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation, either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  #  
 10  # pytilities 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 
 13  # GNU General Public License for more details. 
 14  #  
 15  # You should have received a copy of the GNU General Public License 
 16  # along with pytilities.  If not, see <http://www.gnu.org/licenses/>. 
 17  # 
 18   
 19  __docformat__ = 'reStructuredText' 
 20   
21 -class AttributeCollectionBase(object):
22 """ 23 Mixin, allows extension of instance attributes with `AttributeCollection`s 24 25 This mixin allows a class' instances' attributes and set of supported 26 operators to be extended with `AttributeCollection`s. 27 28 Note: this class provides a base for using `AttributeCollection`s, it is not 29 a base class of `AttributeCollection`. This have been a misnomer. 30 31 Methods: 32 33 - `_append_attribute_collection`: Append a new `AttributeCollection` 34 35 Class invariants: 36 37 1. an `AttributeCollectionBase` never contains two identical 38 `AttributeCollection`s 39 """ 40
41 - def __init__(self):
42 object.__setattr__(self, 43 "_AttributeCollectionBase__collections", [])
44
45 - def _append_attribute_collection(self, collection):
46 """ 47 Append a new `AttributeCollection`. 48 49 When attributes of collections overlap, the first of overlapping 50 attributes found in the lookup process is used and the others are 51 ignored. Lookup happens in the same order as collections were added. (It 52 is probably best to avoid overlaps.) 53 54 Parameters: 55 56 collection :: AttributeCollection 57 the collection to add 58 """ 59 assert collection not in self.__collections, \ 60 "Collection can appear only once in the list of collections of" + \ 61 "the attribute collection base" 62 63 self.__collections.append(collection)
64
65 - def __getattr__(self, name):
66 # NOTE: if you're getting exceptions about this, you probably still 67 # need to call __init__ 68 collections = object.__getattribute__(self, 69 "_AttributeCollectionBase__collections") 70 for collection in collections: 71 (found, value) = collection.getattr_(name) 72 if found: return value 73 74 # reaching this point means no collection contains the attrib 75 raise AttributeError("'%s' object has no attribute '%s'" % 76 (object.__getattribute__(self, "__class__").__name__, name))
77
78 - def __setattr__(self, name, value):
79 try: 80 for collection in self.__collections: 81 found = collection.setattr_(name, value) 82 if found: return 83 except AttributeError: 84 # caused by our init not having been called yet 85 # this can happen when C inherits from A, B and B inherits from us 86 # thus self.__collections doesn't exist yet 87 # or we are createing __colections for the first time 88 pass 89 90 # reaching this point means no collection contains the attrib 91 # let object take care of this one 92 object.__setattr__(self, name, value)
93
94 - def __delattr__(self, name):
95 try: 96 for collection in self.__collections: 97 found = collection.detattr_(name) 98 if found: return 99 except AttributeError: 100 # see __setattr__ 101 pass 102 103 # reaching this point means no collection contains the attrib 104 # let object take care of this one 105 object.__delattr__(self, name)
106 107 108 ######################################################################## 109 # A big bunch of things aren't searched for on the instance, but on the 110 # class Thus, they don't call __getattr__, __getattribute__, ... We'll just 111 # 'fix' that by placing them on our class and routing them through to the 112 # __getattr__ methods etc. 113
114 - def __str__(self):
115 return self.__getattr__("__str__")()
116
117 - def __copy__(self):
118 return self.__getattr__("__copy__")()
119
120 - def __eq__(self, other):
121 return self.__getattr__("__eq__")(other)
122
123 - def __neq__(self, other):
124 return self.__getattr__("__neq__")(other)
125
126 - def __nonzero__(self):
127 try: 128 return self.__getattr__("__nonzero__")() 129 except AttributeError: 130 return True # the default behaviour
131
132 - def __len__(self):
133 return self.__getattr__("__len__")()
134
135 - def __getitem__(self, key):
136 return self.__getattr__("__getitem__")(key)
137
138 - def __setitem__(self, key, value):
139 self.__getattr__("__setitem__")(key, value)
140
141 - def __iter__(self):
142 return self.__getattr__("__iter__")()
143
144 - def __add__(self, other):
145 return self.__getattr__("__add__")(other)
146
147 - def __iadd__(self, other):
148 return self.__getattr__("__iadd__")(other)
149
150 - def __sub__(self, other):
151 return self.__getattr__("__sub__")(other)
152
153 - def __mul__(self, other):
154 return self.__getattr__("__mul__")(other)
155
156 - def __rmul__(self, other):
157 return self.__getattr__("__rmul__")(other)
158
159 - def __imul__(self, other):
160 return self.__getattr__("__imul__")(other)
161
162 - def __div__(self, other):
163 return self.__getattr__("__div__")(other)
164
165 - def __rdiv__(self, other):
166 return self.__getattr__("__rdiv__")(other)
167
168 - def __floordiv__(self, other):
169 return self.__getattr__("__floordiv__")(other)
170
171 - def __rfloordiv__(self, other):
172 return self.__getattr__("__rfloordiv__")(other)
173
174 - def __truediv__(self, other):
175 return self.__getattr__("__truediv__")(other)
176
177 - def __rtruediv__(self, other):
178 return self.__getattr__("__rtruediv__")(other)
179
180 - def __neg__(self):
181 return self.__getattr__("__neg__")()
182
183 - def __pos__(self):
184 return self.__getattr__("__pos__")()
185
186 - def __abs__(self):
187 return self.__getattr__("__abs__")()
188 189 # TODO: test all ops for the expected fail, just like with an object, for 190 # unimplemented ops 191