Package pyffi :: Package object_models :: Module array_type
[hide private]
[frames] | no frames]

Source Code for Module pyffi.object_models.array_type

  1  """Defines base class for arrays of data.""" 
  2   
  3  # -------------------------------------------------------------------------- 
  4  # ***** BEGIN LICENSE BLOCK ***** 
  5  # 
  6  # Copyright (c) 2007-2011, Python File Format Interface 
  7  # All rights reserved. 
  8  # 
  9  # Redistribution and use in source and binary forms, with or without 
 10  # modification, are permitted provided that the following conditions 
 11  # are met: 
 12  # 
 13  #    * Redistributions of source code must retain the above copyright 
 14  #      notice, this list of conditions and the following disclaimer. 
 15  # 
 16  #    * Redistributions in binary form must reproduce the above 
 17  #      copyright notice, this list of conditions and the following 
 18  #      disclaimer in the documentation and/or other materials provided 
 19  #      with the distribution. 
 20  # 
 21  #    * Neither the name of the Python File Format Interface 
 22  #      project nor the names of its contributors may be used to endorse 
 23  #      or promote products derived from this software without specific 
 24  #      prior written permission. 
 25  # 
 26  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 27  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 28  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 29  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 30  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 31  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 32  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 33  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 34  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 35  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 36  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 37  # POSSIBILITY OF SUCH DAMAGE. 
 38  # 
 39  # ***** END LICENSE BLOCK ***** 
 40  # -------------------------------------------------------------------------- 
 41   
 42  from itertools import izip 
 43   
 44  from pyffi.object_models.any_type import AnyType 
 45  import pyffi.object_models.simple_type 
 46  from pyffi.utils.graph import EdgeFilter 
47 48 -class ValidatedList(list):
49 """Abstract base class for lists whose items can be validated (for 50 instance, for type checks). 51 """
52 - def __init__(self, *args, **kwargs):
53 """Initialize empty list.""" 54 list.__init__(self, *args, **kwargs) 55 for item in list.__iter__(self): 56 self.validate(item)
57 58 @classmethod
59 - def validate(cls, item):
60 """Checks that the item can be added to the list.""" 61 raise NotImplementedError
62
63 - def __setitem__(self, index, item):
64 """Set item at given index.""" 65 # set the new item 66 self.validate(item) 67 list.__setitem__(self, index, item)
68
69 - def append(self, item):
70 """Validate item and append to list.""" 71 self.validate(item) 72 list.append(self, item)
73
74 - def extend(self, other):
75 """Validate items and extend list.""" 76 # make a list copy of other 77 otherlist = list(other) 78 # validate each item of other 79 for item in otherlist: 80 self.validate(item) 81 # extend 82 list.extend(self, otherlist)
83
84 - def insert(self, index, item):
85 """Validate item and insert.""" 86 self.validate(item) 87 list.insert(self, index, item)
88
89 -class AnyArray(ValidatedList, AnyType):
90 """Abstract base class for all array types. 91 92 @cvar _MAXSTR: Maximum number of elements to write in the L{__str__} method. 93 :type _MAXSTR: ``int`` 94 """ 95 96 _MAXSTR = 16 97
98 - def is_interchangeable(self, other):
99 """Check if array's are interchangeable.""" 100 # compare classes 101 if not(self.__class__ is other.__class__): 102 return False 103 # compare lengths 104 if list.__len__(self) != list.__len__(other): 105 return False 106 # compare elements 107 for item, otheritem in izip(list.__iter__(self), list.__iter__(other)): 108 if not item.is_interchangeable(otheritem): 109 return False 110 # all elements are interchangeable, so the array is as well 111 return True
112
113 - def __str__(self):
114 """String representation. 115 116 :return: String representation. 117 :rtype: ``str`` 118 """ 119 # TODO use getDetailTypeName 120 result = "%s array:\n" % self.ItemType.__name__ 121 more = False 122 for itemnum, item in enumerate(self): 123 if itemnum >= self._MAXSTR: 124 more = True 125 break 126 result += " [%02i] %s\n" % (itemnum, item) 127 if more: 128 result += (" ... (%i more following)\n" 129 % (len(self) - self._MAXSTR)) 130 return result
131
132 - def get_detail_child_nodes(self, edge_filter=EdgeFilter()):
133 return list.__iter__(self)
134
135 - def get_detail_child_names(self, edge_filter=EdgeFilter()):
136 return ("[%i]" % i for i in xrange(list.__len__(self)))
137
138 -class MetaUniformArray(type):
139 """Metaclass for L{UniformArray}. Checks that 140 L{ItemType<UniformArray.ItemType>} is an 141 L{AnyType<pyffi.object_models.any_type.AnyType>} subclass. 142 """
143 - def __init__(cls, name, bases, dct):
144 """Initialize array type.""" 145 # create the class 146 super(MetaUniformArray, cls).__init__(name, bases, dct) 147 # check type of elements 148 if not issubclass(cls.ItemType, AnyType): 149 raise TypeError("array ItemType must be an AnyType subclass")
150
151 -class UniformArray(AnyArray):
152 """Wrapper for array with elements of the same type; this type must be 153 a subclass of L{pyffi.object_models.any_type.AnyType}. 154 155 >>> from pyffi.object_models.simple_type import SimpleType 156 >>> class MyInt(SimpleType): 157 ... # in practice one would implement some sort of type checking 158 ... # for this example we keep it simple 159 ... def __init__(self, value=0): 160 ... self._value = value 161 >>> class ListOfInts(UniformArray): 162 ... ItemType = MyInt 163 >>> testlist = ListOfInts() 164 >>> testlist.append(MyInt(value=20)) 165 >>> testlist.extend([MyInt(value=val) for val in range(2, 10, 2)]) 166 >>> print(testlist) 167 MyInt array: 168 [00] 20 169 [01] 2 170 [02] 4 171 [03] 6 172 [04] 8 173 <BLANKLINE> 174 >>> [item.value for item in testlist[::-2]] 175 [8, 4, 20] 176 177 @cvar ItemType: Type of the elements of this array. 178 :type ItemType: L{pyffi.object_models.any_type.AnyType} 179 """ 180 181 __metaclass__ = MetaUniformArray 182 ItemType = AnyType 183 184 @classmethod
185 - def validate(cls, item):
186 """Check if item can be added.""" 187 if not item.__class__ is cls.ItemType: 188 raise TypeError("item has incompatible type (%s, not %s)" 189 % (item.__class__.__name__, 190 cls.ItemType.__name__))
191
192 -class MetaUniformSimpleArray(type):
193 """Metaclass for L{UniformSimpleArray}. Checks that 194 L{ItemType<UniformSimpleArray.ItemType>} is an 195 L{SimpleType<pyffi.object_models.simple_type.SimpleType>} subclass. 196 """
197 - def __init__(cls, name, bases, dct):
198 """Initialize array type.""" 199 # create the class 200 super(MetaUniformSimpleArray, cls).__init__(name, bases, dct) 201 # check type of elements 202 if not issubclass(cls.ItemType, 203 pyffi.object_models.simple_type.SimpleType): 204 raise TypeError("array ItemType must be a SimpleType subclass")
205
206 -class UniformSimpleArray(AnyArray):
207 """Base class for array's with direct access to values of simple items.""" 208 209 __metaclass__ = MetaUniformSimpleArray 210 ItemType = pyffi.object_models.simple_type.SimpleType 211
212 - def __getitem__(self, index):
213 # using list base method for speed 214 return list.__getitem__(self, index).value
215
216 - def __setitem__(self, index, value):
217 # using list base method to skip validation 218 list.__getitem__(self, index).value = value
219
220 - def __iter__(self):
221 return (item.value for item in list.__iter__(self))
222
223 - def __contains__(self, value):
224 return value in (item.value for item in list.__iter__(self))
225
226 - def append(self, value):
227 # using list base method to skip validation 228 list.append(self, self.ItemType(value))
229
230 - def count(self, value):
231 """@warning: not efficient.""" 232 # count in list of values 233 list(self.__iter__()).count(value)
234
235 - def extend(self, other):
236 """Extend list.""" 237 # using list base method to skip validation 238 list.extend(self, (self.ItemType(value) for value in other))
239
240 - def index(self, value):
241 """@warning: not efficient.""" 242 return list(self.__iter__()).index(value)
243
244 - def insert(self, index, value):
245 """Insert.""" 246 # using list base method for speed 247 list.insert(self, index, self.ItemType(value))
248
249 - def pop(self, index=-1):
250 return list.pop(self, index).value
251
252 - def remove(self, value):
253 """@warning: not efficient.""" 254 self.list.pop(self, self.index(value))
255