Package VisionEgg :: Module ParameterTypes
[frames] | no frames]

Source Code for Module VisionEgg.ParameterTypes

  1  # The Vision Egg: ParameterTypes 
  2  # 
  3  # Copyright (C) 2001-2003 Andrew Straw 
  4  # Copyright (C) 2005,2008 California Insitute of Technology 
  5  # 
  6  # URL: <http://www.visionegg.org/> 
  7  # 
  8  # Distributed under the terms of the GNU Lesser General Public License 
  9  # (LGPL). See LICENSE.TXT that came with this file. 
 10   
 11  """ 
 12  Type checking for the Vision Egg. 
 13   
 14  """ 
 15   
 16  import VisionEgg 
 17   
 18  import types, warnings 
 19  import numpy 
 20  import numpy.oldnumeric as numpyNumeric 
 21   
 22  array_types = [numpy.ndarray] 
 23  # Allow use of numarray and original Numeric Texture data without requiring either 
 24  try: 
 25      import numarray 
 26      array_types.append( numarray.numarraycore.NumArray ) 
 27  except ImportError: 
 28      pass 
 29  try: 
 30      import Numeric as orig_Numeric 
 31      array_types.append( orig_Numeric.ArrayType ) 
 32  except ImportError: 
 33      pass 
 34   
35 -class ParameterTypeDef(object):
36 """Base class for all parameter type definitions"""
37 - def verify(value):
38 # override this method with type-checking code 39 raise RuntimeError('must override base class method verify')
40 verify = staticmethod(verify)
41
42 -def get_all_classes_list(klass):
43 #assert(type(klass) == types.ClassType) 44 result = [klass] 45 for base_klass in klass.__bases__: 46 result.extend(get_all_classes_list(base_klass)) 47 return result
48
49 -def is_parameter_type_def(item_type):
50 if type(item_type) == types.ClassType: 51 if Sequence in get_all_classes_list(item_type): 52 raise TypeError("Sequence definition must be an instance (with a contained type).") 53 else: 54 return ParameterTypeDef in get_all_classes_list(item_type) 55 elif isinstance(item_type,ParameterTypeDef): 56 return True 57 elif issubclass(item_type,ParameterTypeDef): # for new style classes 58 return True 59 elif item_type == types.NoneType: 60 warnings.warn("types.NoneType will stop being a supported type "+\ 61 "argument. Please call "+\ 62 "VisionEgg.ParameterTypes.get_type(None) to get the "+\ 63 "supported value",DeprecationWarning,stacklevel=2) 64 return True 65 else: 66 return False
67
68 -class AnyOf(ParameterTypeDef):
69 - def __init__(self,*item_types):
70 for item_type in item_types: 71 if not is_parameter_type_def(item_type): 72 raise TypeError("%s is not a valid type definition") 73 self.item_types = item_types
74 - def __str__(self):
75 return 'AnyOf(%s)'%(' or '.join(map(str,self.item_types)))
76 - def verify(self,is_any_of):
77 for item_type in self.item_types: 78 if item_type.verify(is_any_of): 79 return True 80 return False
81 - def get_item_types(self):
82 return self.item_types
83
84 -class NoneMC(type):
85 """metaclass for NoneType"""
86 - def __str__(self):
87 return 'None'
88
89 -class NoneType(ParameterTypeDef):
90 __metaclass__ = NoneMC
91 - def verify(is_none):
92 return is_none is None
93 verify = staticmethod(verify)
94
95 -class BooleanMC(type):
96 """metaclass for Boolean"""
97 - def __str__(self):
98 return 'Boolean'
99
100 -class Boolean(ParameterTypeDef):
101 __metaclass__ = BooleanMC
102 - def verify(is_boolean):
103 if isinstance(is_boolean,(bool,int,numpy.integer)): 104 return True 105 else: 106 return False
107 verify = staticmethod(verify)
108
109 -class CallableMC(type):
110 """metaclass for Callable"""
111 - def __str__(self):
112 return 'Callable'
113
114 -class Callable(ParameterTypeDef):
115 __metaclass__ = CallableMC
116 - def verify(is_callable):
117 return callable(is_callable)
118 verify = staticmethod(verify)
119
120 -class AnyClassMC(type):
121 """metaclass for AnyClass"""
122 - def __str__(self):
123 return 'AnyClass'
124
125 -class AnyClass(ParameterTypeDef):
126 """parameter is a class""" 127 __metaclass__ = AnyClassMC
128 - def verify(is_class):
129 return type(is_class) == types.ClassType
130 verify = staticmethod(verify)
131
132 -class SubClass(ParameterTypeDef):
133 """parameter is derived from base_class"""
134 - def __init__(self,base_class):
135 if type(base_class) != types.ClassType: 136 raise TypeError("base_class must be ClassType") 137 self.base_class = base_class
138 - def verify(self,is_class):
139 if type(self.base_class) != types.ClassType: 140 return False 141 return self.base_class in get_all_classes_list(is_class)
142 - def __str__(self):
143 return 'SubClass of %s'%str(self.base_class)
144
145 -class Instance(ParameterTypeDef):
146 """parameter is an instance of class_type"""
147 - def __init__(self,class_type):
148 if type(class_type) not in (types.ClassType, types.TypeType): 149 raise TypeError("expected a class type") 150 self.class_type = class_type
151 - def __str__(self):
152 contained_string = str(self.class_type) 153 return 'Instance of %s'%contained_string
154 - def verify(self,is_instance):
155 return isinstance(is_instance,self.class_type)
156
157 -class IntegerMC(type):
158 """metaclass for Integer"""
159 - def __str__(self):
160 return 'Integer'
161
162 -class Integer(ParameterTypeDef):
163 __metaclass__ = IntegerMC
164 - def verify(is_integer):
165 return isinstance(is_integer,(int,numpy.integer))
166 verify = staticmethod(verify)
167
168 -class UnsignedIntegerMC(IntegerMC):
169 """metaclass for UnsignedInteger"""
170 - def __str__(self):
171 return 'UnsignedInteger'
172
173 -class UnsignedInteger(Integer):
174 __metaclass__ = UnsignedIntegerMC
175 - def verify(is_unsigned_integer):
176 if not Integer.verify(is_unsigned_integer): 177 return False 178 return is_unsigned_integer >= 0
179 verify = staticmethod(verify)
180
181 -class RealMC(type):
182 """metaclass for Real"""
183 - def __str__(self):
184 return 'Real'
185
186 -class Real(ParameterTypeDef):
187 __metaclass__ = RealMC
188 - def verify(is_real):
189 if isinstance(is_real, (int, float, numpy.floating, numpy.integer)): 190 return True 191 elif type(is_real) in array_types: 192 # scalars can be Numeric arrays 193 if len(is_real.shape)==0: 194 try: 195 float(is_real) 196 return True 197 except: 198 return False 199 return False
200 verify = staticmethod(verify)
201
202 -class Sequence(ParameterTypeDef):
203 """A tuple, list or Numeric array"""
204 - def __init__(self,item_type):
205 if not is_parameter_type_def(item_type): 206 raise TypeError("%s is not a valid type definition"%item_type) 207 self.item_type = item_type
208 - def __str__(self):
209 contained_string = str(self.item_type) 210 return 'Sequence of %s'%contained_string
211 - def verify(self,is_sequence):
212 try: 213 len(is_sequence) 214 except TypeError: 215 return False 216 for i in xrange(len(is_sequence)): 217 if not self.item_type.verify(is_sequence[i]): 218 return False 219 return True
220
221 -class Sequence2(Sequence):
222 - def __str__(self):
223 contained_string = str(self.item_type) 224 return 'Sequence2 of %s'%contained_string
225 - def verify(self,is_sequence2):
226 if not Sequence.verify(self,is_sequence2): 227 return False 228 if not len(is_sequence2) == 2: 229 return False 230 return True
231
232 -class Sequence3(Sequence):
233 - def __str__(self):
234 contained_string = str(self.item_type) 235 return 'Sequence3 of %s'%contained_string
236 - def verify(self,is_sequence3):
237 if not Sequence.verify(self,is_sequence3): 238 return False 239 if not len(is_sequence3) == 3: 240 return False 241 return True
242
243 -class Sequence4(Sequence):
244 - def __str__(self):
245 contained_string = str(self.item_type) 246 return 'Sequence4 of %s'%contained_string
247 - def verify(self,is_sequence4):
248 if not Sequence.verify(self,is_sequence4): 249 return False 250 if not len(is_sequence4) == 4: 251 return False 252 return True
253
254 -class Sequence4x4(Sequence4):
255 - def __str__(self):
256 contained_string = str(self.item_type) 257 return 'Sequence4x4 of %s'%contained_string
258 - def verify(self,is_sequence4x4):
259 try: 260 len(is_sequence4x4) 261 except TypeError: 262 return False 263 if not len(is_sequence4x4) == 4: 264 return False 265 for i in range(4): 266 if not Sequence4.verify(self,is_sequence4x4[i]): 267 return False 268 return True
269
270 -class StringMC(type):
271 """metaclass for String"""
272 - def __str__(self):
273 return 'String'
274
275 -class String(ParameterTypeDef):
276 __metaclass__ = StringMC
277 - def verify(is_string):
278 if isinstance(is_string,str): 279 return True 280 else: 281 return False
282 verify = staticmethod(verify)
283
284 -class UnicodeMC(type):
285 """metaclass for Unicode"""
286 - def __str__(self):
287 return 'Unicode'
288
289 -class Unicode(ParameterTypeDef):
290 __metaclass__ = UnicodeMC
291 - def verify(is_unicode):
292 if isinstance(is_unicode,unicode): 293 return True 294 else: 295 return False
296 verify = staticmethod(verify)
297
298 -def get_type(value):
299 """Take a value and return best guess of ParameterTypeDef it is.""" 300 py_type = type(value) 301 302 if isinstance(value,bool): 303 return Boolean 304 elif value is None: 305 return NoneType 306 elif isinstance(value,(int,numpy.integer)): 307 if py_type >= 0: 308 return UnsignedInteger 309 else: 310 return Integer 311 elif isinstance(value,(float,numpy.floating)): 312 return Real 313 elif py_type == types.InstanceType: 314 # hmm, impossible to figure out appropriate class of all possible base classes 315 return Instance(value.__class__) 316 elif callable(value): 317 return Callable 318 else: 319 try: 320 len(value) 321 except TypeError: 322 is_sequence = False 323 else: 324 is_sequence = True 325 if is_sequence: 326 if len(value) == 4: 327 # see if it's a 4x4 sequence 328 is_sequence4x4 = True 329 for i in range(4): 330 try: 331 len(value[i]) 332 except TypeError: 333 is_sequence4x4 = False 334 if is_sequence4x4: 335 sequence4x4_type = get_type(value[0][0]) # XXX assume all same types 336 return Sequence4x4(sequence4x4_type) 337 if type(value) == str: 338 return String 339 lcd_type = get_type(value[0]) # lowest common denominator type 340 for i in range(len(value)): 341 this_type = get_type(value[i]) 342 if lcd_type != this_type: 343 # find lowest common denominator type 344 if lcd_type.verify( this_type ): 345 continue # covered by lowest common denominator 346 elif this_type.verify( lcd_type ): 347 lcd_type = this_type # new lowest common denominator 348 else: 349 lcd_type = AnyOf( lcd_type, this_type ) # make new lowest common denominator 350 sequence_type = lcd_type 351 if len(value) == 2: 352 return Sequence2(sequence_type) 353 elif len(value) == 3: 354 return Sequence3(sequence_type) 355 elif len(value) == 4: 356 return Sequence4(sequence_type) 357 else: 358 return Sequence(sequence_type) 359 # finally, one last check: 360 if isinstance(value, object): 361 # new style class 362 # hmm, impossible to figure out appropriate class of all possible base classes 363 return Instance(value.__class__) 364 else: 365 raise TypeError("Unable to determine type for '%s'"%value)
366
367 -def assert_type(check_type,require_type):
368 if not is_parameter_type_def(check_type): 369 raise ValueError("require a ParameterTypeDef as argument (not %s)"%check_type) 370 if not is_parameter_type_def(require_type): 371 raise ValueError("require a ParameterTypeDef as argument (not %s)"%require_type) 372 if check_type == require_type: 373 return 374 375 if check_type in (Integer,UnsignedInteger) and require_type == Boolean: 376 return # let integers pass as booleans 377 # XXX doesn't check if Instance is actually instance of proper class 378 if isinstance(check_type,ParameterTypeDef): 379 check_class = check_type.__class__ 380 else: 381 check_class = check_type 382 383 if isinstance(require_type,ParameterTypeDef): 384 if isinstance(require_type,AnyOf): 385 passed = False 386 for ok_type in require_type.get_item_types(): 387 try: 388 assert_type(check_type, ok_type ) 389 return # it's ok 390 except: 391 pass 392 else: 393 require_class = require_type.__class__ 394 else: 395 require_class = require_type 396 397 if require_class in get_all_classes_list(check_class): 398 return 399 400 if issubclass(require_class,Real): 401 if issubclass(check_class,Boolean): 402 return 403 elif issubclass(check_class,Integer): 404 return 405 406 if issubclass(require_class,Integer): 407 if issubclass(check_class,Boolean): 408 return 409 410 raise TypeError("%s not of type %s"%(check_type,require_type))
411