Package NetworkEditor :: Module datatypes
[hide private]
[frames] | no frames]

Source Code for Module NetworkEditor.datatypes

  1  ######################################################################## 
  2  # 
  3  # Date: Nov. 2001  Author: Michel Sanner, Daniel Stoffler 
  4  # 
  5  #       sanner@scripps.edu 
  6  #       stoffler@scripps.edu 
  7  # 
  8  #       The Scripps Research Institute (TSRI) 
  9  #       Molecular Graphics Lab 
 10  #       La Jolla, CA 92037, USA 
 11  # 
 12  # Copyright: Michel Sanner, Daniel Stoffler and TSRI 
 13  # 
 14  # Revision: Guillaume Vareille 
 15  # 
 16  ######################################################################### 
 17   
 18  import types 
 19  import Numeric 
 20  import warnings 
 21  import array    
 22   
 23   
24 -class AnyArrayType(dict):
25 """Base class for defining types of Ports which can handle single values 26 or arrays of arbitrary shape. 27 28 this class must be herited only !!!! get inspired by class IntType below 29 30 the construcor arguments are: 31 32 name: string used to identify an instance of a AnyArrayType object 33 ex: float 34 35 you can add the datashape to the name 36 ex: float(0,>=3,4,0)' 37 38 Multi dimensional arrays can be specified by passing 39 a datashape in parenthesis in the form of a string of comma separated 40 expressions. The number of expressions is the number of dimensions. 41 Valid expressions are : 42 0 : meaning there is no condition on this dimension. 43 (in addition, the leading 0 dimensions are optional) 44 x : length of this dimension must be x 45 >x : length of this dimension must be > x 46 <x : length of this dimension must be < x 47 >=x: length of this dimension must be >= x 48 <=x: length of this dimension must be <= x 49 50 for instance a list of vertices can be represented by float(0,3) 51 float: describe the smalest elementary datum (one coordinate). 52 you can introduce your own elementary type 53 (generaly inheriting basic types), this allow you to easily 54 define color and shape for this type (see InstancematType below) 55 56 3: because there are 3 coordinates per vertex. 57 0: because we don't have any limitation on the number of vertices. 58 It is a leading 0, therefore this dimension is optionnal 59 (meaning: if you're passing a single vertex [x,y,z], 60 your are not oblige to put it in a list. 61 ex: you can give [x,y,z] or [[x,y,z]]) 62 63 """
64 - def __init__(self, 65 # used as a key the datatype manager 66 name='None', 67 datashape=None, # describe (0,>=3) 68 klass=None, # class of Python object passing through port. 69 # This is used for data type propagation 70 dataDescr=None, # string describing data in tool tip 71 color=None, # color of port icon 72 shape='diamond', # shape used for port icon 73 width=None, height=None, # width and height of port icon 74 ):
75 #import traceback;traceback.print_stack() 76 #print "AnyArrayType __init__ name datashape", name, datashape 77 78 self['name'] = name 79 self['datashape'] = datashape 80 self['class'] = klass 81 self['dataDescr'] = dataDescr 82 83 if color is None: 84 color = 'white' 85 self['color'] = color # port icon color 86 87 if shape is None: 88 shape = self._shape(datashape) 89 self['shape'] = shape # port icon 90 91 if width is None: 92 width = 12 93 self['width'] = width # port icon width 94 95 if height is None: 96 if shape == 'circle' or shape == 'square': 97 height = self['width'] 98 else: 99 height = 8 100 self['height'] = height # port icon height 101 102 # list of lambda functions used to check dimension of incoming data 103 self.dimensionTest = [] 104 105 # compile dimension checking functions that will be used in validate 106 if datashape is None: 107 self.lenDimensionTest = 0 108 else: 109 110 for dimlim in datashape[1:-1].split(','): 111 # this case should be handled using >=1, i.e. required 112 # dimension with no constriaint 113 #if dimlim=='': # no restirction on this dimension 114 # self.dimensionTest.append( None ) 115 116 if dimlim.isdigit(): # we have a fixed extent for this dimension 117 if int(dimlim)!=0: 118 self.dimensionTest.append( lambda x: x==int(dimlim) ) 119 else: # no restriction on this dimension 120 self.dimensionTest.append( None ) 121 else: 122 strg = '' 123 for c in dimlim: 124 if c in ['>', '<']: 125 strg += 'x '+c 126 else: 127 strg += c 128 self.dimensionTest.append( eval('lambda x: %s'%strg) ) 129 130 self.lenDimensionTest = len(self.dimensionTest)
131 132
133 - def validateDims(self, data):
134 """data comes in as a numeric array, and returns True if required 135 shapes pass tests, returns False is tests fail, or returns number of missing 136 dimensions if test pass but optional dims are missing 137 """ 138 139 missingDimensions = self.lenDimensionTest - len(data.shape) 140 for i in range(missingDimensions): 141 data.shape = (1,) + data.shape 142 143 for dim,f in zip(data.shape, self.dimensionTest): 144 if f is not None: 145 if not f(dim): 146 return False, data 147 148 if missingDimensions > 0: 149 return missingDimensions, data 150 else: 151 return True, data
152 153
154 - def _shape(self, datashape):
155 """This function is called by the constructor to return the number of 156 edges used to draw the port icon based on the number of dimensions of the type. 157 NOTE: this function is only used if the icon shape is not specified as an 158 argument to the constructor. 159 """ 160 if datashape is not None: 161 lDimensions = datashape[1:-1].split(',') 162 lShape = len(lDimensions) * 2 - 1 163 if lDimensions[0] == '0': 164 lShape -= 1 165 else: 166 lShape = 0 167 #print "icon shape:", lShape 168 return lShape
169 170
171 - def cast(self, data):
172 return False, None
173 174
175 - def validate(self, data):
176 if self['class'] is None: 177 return True, data 178 if self['datashape'] is None: 179 if isinstance(data, self['class']): 180 return True, data 181 else: 182 return False, None 183 try: 184 lArray = Numeric.array(data) 185 lArray0 = lArray[0] 186 while hasattr(lArray0,'shape'): 187 lArray0 = lArray0[0] 188 if isinstance(lArray0, self['class']): 189 return True, lArray 190 else: 191 return False, None 192 except: 193 return False, None
194 195 196 # DEPRECATED CLASS: use AnyArrayType instead 197 from UserDict import UserDict
198 -class AnyType( 199 UserDict 200 # , 201 # AnyArrayType 202 ):
203
204 - def __init__(self, name='Old None', color='white', shape='diamond', 205 width=12, height=8, klass=None, dataDescr=None 206 # , datashape=None 207 ):
208 UserDict.__init__(self) 209 # AnyArrayType.__init__(self, name=name, color=color, 210 # shape=shape, width=width, height=height, 211 # klass=klass, dataDescr=dataDescr, 212 # datashape=datashape) 213 214 # warnings.warn('AnyType is deprecated, use AnyArrayType instead', 215 # DeprecationWarning, stacklevel=2) 216 217 # Note: use EVEN numbers for width, height, since they will be 218 # divided by 2 for halfPortWidth, halfPortHeight 219 self.data['name'] = name 220 self.data['dataDescr'] = dataDescr 221 self.data['shape'] = shape # port icon 222 self.data['width'] = width # port icon width 223 self.data['height'] = height # port icon height 224 self.data['color'] = color # port icon color 225 self.data['class'] = klass 226 self.data['datashape'] = None # added to be compatible with
227 228
229 - def cast(self, data):
230 """returns a success status (true, false) and the coerced data""" 231 assert True, data # to silent pychecker 232 return False, None
233 234
235 - def validate(self, data):
236 """returns true if data if of the proper type""" 237 return True
238 239 240
241 -class FloatType(AnyArrayType):
242
243 - def __init__(self, name='float', datashape=None, color='green', 244 shape='circle', width=None, height=None):
245 AnyArrayType.__init__(self, name=name, color=color, 246 shape=shape, width=width, height=height, 247 klass=float, datashape=datashape)
248 249
250 - def validate(self, data):
251 if self['datashape'] is None: 252 if type(data) == types.FloatType: 253 return True, data 254 else: 255 return False, None 256 try: 257 lArray = Numeric.array(data, 'f') 258 return True, lArray 259 except: 260 return False, None
261 262
263 - def cast(self, data):
264 if self['datashape'] is None: 265 if type(data) == types.FloatType: 266 return True, data 267 try: 268 data = float(data) 269 return True, data 270 except: 271 return False, data 272 try: 273 lArray = (Numeric.array(data)).astype('f') 274 return True, lArray 275 except: 276 return False, None
277 278 279
280 -class IntType(AnyArrayType):
281
282 - def __init__(self, name='int', datashape=None,color='yellow', 283 shape='circle', width=None, height=None):
284 AnyArrayType.__init__(self, name=name, color=color, 285 shape=shape, width=width, height=height, 286 klass=int, datashape=datashape)
287 288
289 - def validate(self, data):
290 if self['datashape'] is None: 291 if type(data) == types.IntType: 292 return True, data 293 else: 294 return False, None 295 try: 296 lArray = Numeric.array(data, 'i') 297 return True, lArray 298 except: 299 return False, None
300 301
302 - def cast(self, data):
303 if self['datashape'] is None: 304 if type(data) == types.IntType: 305 return True, data 306 try: 307 data = int(data) 308 return True, data 309 except: 310 return False, data 311 try: 312 lArray = (Numeric.array(data)).astype('i') 313 return True, lArray 314 except: 315 return False, None
316 317 318
319 -class BooleanType(AnyArrayType):
320
321 - def __init__(self, name='boolean', datashape=None, color='yellow', 322 shape='rect', width=None, height=None):
323 324 AnyArrayType.__init__(self, name=name, color=color, 325 shape=shape, width=width, height=height, 326 klass=bool, datashape=datashape)
327 328
329 - def validate(self, data):
330 if self['datashape'] is None: 331 if type(data) == types.BooleanType: 332 return True, data 333 else: 334 return False, None 335 try: 336 array = Numeric.array(data, 'b') 337 return True, array 338 except: 339 return False, None
340 341
342 - def cast(self, data):
343 if self['datashape'] is None: 344 if type(data) == types.BooleanType: 345 return True, data 346 try: 347 data = bool(data) 348 return True, data 349 except: 350 return False, data 351 try: 352 #FIXME: this 'b' stands for binary not boolean 353 lArray = (Numeric.array(data)).astype('b') 354 return True, lArray 355 except: 356 return False, None
357 358 359
360 -class StringType(AnyArrayType):
361
362 - def __init__(self, name='string', datashape=None, color='white', 363 shape='oval', width=None, height=None):
364 365 AnyArrayType.__init__(self, name=name, color=color, 366 shape=shape, width=width, height=height, 367 klass=str, datashape=datashape)
368 369
370 - def validate(self, data):
371 if self['datashape'] is None: 372 if type(data) == types.StringType: 373 return True, data 374 else: 375 return False, None 376 try: 377 array = Numeric.array(data, 'O') 378 #lShape = array.shape 379 #array = map(str, array) 380 #array.shape = lShape 381 return True, array 382 except: 383 return False, None
384 385
386 - def cast(self, data):
387 if self['datashape'] is None: 388 if type(data) == types.StringType: 389 return True, data 390 try: 391 data = str(data) 392 return True, data 393 except: 394 return False, data 395 try: 396 lArray = (Numeric.array(data)).astype('O') 397 return True, lArray 398 except: 399 return False, None
400 401 402 403 #class StringType(AnyType): 404 # 405 # def __init__(self): 406 # AnyType.__init__(self) 407 # self.data['name'] = 'string' 408 # self.data['color'] = 'white' 409 # self.data['shape'] = 'oval' 410 # self.data['width'] = 12 # circle 411 # self.data['height'] = 12 412 # self.data['class'] = str 413 # 414 # def validate(self, data): 415 # return type(data)==types.StringType 416 # 417 # def cast(self, data): 418 # try: 419 # return True, str(data) 420 # except: 421 # return False, data 422 423 424
425 -class ListType(AnyType):
426
427 - def __init__(self):
428 AnyType.__init__(self) 429 self.data['name'] = 'list' 430 self.data['color'] = 'cyan' 431 self.data['shape'] = 'oval' 432 self.data['width'] = 12 # circle 433 self.data['height'] = 12 434 self.data['class'] = list
435 436
437 - def validate(self, data):
438 return type(data)==types.ListType
439 440
441 - def cast(self, data):
442 try: 443 data = list(data) 444 return True, data 445 except: 446 return False, data
447 448 449
450 -class TupleType(AnyType):
451
452 - def __init__(self):
453 AnyType.__init__(self) 454 self.data['name'] = 'tuple' 455 self.data['color'] = 'cyan' 456 self.data['shape'] = 'oval' 457 self.data['width'] = 12 # circle 458 self.data['height'] = 12 459 self.data['class'] = tuple
460 461
462 - def validate(self, data):
463 return type(data)==types.TupleType
464 465
466 - def cast(self, data):
467 try: 468 data = tuple(data) 469 return True, data 470 except: 471 return False, data
472 473 474
475 -class DictType(AnyType):
476
477 - def __init__(self):
478 AnyType.__init__(self) 479 self.data['name'] = 'dict' 480 self.data['color'] = 'cyan' 481 self.data['shape'] = 'oval' 482 self.data['width'] = 12 # circle 483 self.data['height'] = 12 484 self.data['class'] = dict
485 486
487 - def validate(self, data):
488 return type(data)==types.DictType
489 490 491
492 -class ArrayType(AnyType):
493
494 - def __init__(self):
495 AnyType.__init__(self) 496 self.data['name'] = 'array' 497 self.data['color'] = 'cyan' 498 self.data['shape'] = 'oval' 499 self.data['width'] = 12 # circle 500 self.data['height'] = 12 501 self.data['class'] = array.array
502 503
504 - def validate(self, data):
505 return isinstance(data, array.ArrayType)
506 507 508
509 -class NumericArrayType(AnyType):
510
511 - def __init__(self):
512 AnyType.__init__(self) 513 self.data['name'] = 'NumericArray' 514 self.data['color'] = 'orange' 515 self.data['shape'] = 'pentagon' 516 self.data['class'] = Numeric.array
517 518
519 - def validate(self, data):
520 return isinstance(data, Numeric.ArrayType)
521 522
523 - def cast(self, data):
524 try: 525 data = Numeric.array(data) 526 return True, data 527 except: 528 return False, data
529 530 531
532 -class VectorType(AnyType):
533
534 - def __init__(self):
535 AnyType.__init__(self) 536 self.data['name'] = 'vector' 537 self.data['color'] = 'cyan' 538 self.data['shape'] = 'oval' 539 self.data['width'] = 12 # circle 540 self.data['height'] = 12 541 self.data['class'] = None
542 543
544 - def validate(self, data):
545 try: 546 if type(data) != types.StringType: 547 len(data) 548 return True 549 else: 550 return False 551 except: 552 return False
553 554
555 - def cast(self, data):
556 """returns a success status (true, false) and the coerced data 557 """ 558 if type(data) == types.StringType: 559 return True, (data, ) 560 return False, None
561 562 563
564 -class TriggerOut(AnyType):
565
566 - def __init__(self):
567 AnyType.__init__(self) 568 self.data['name'] = 'triggerOut' 569 self.data['color'] = 'orange' 570 self.data['shape'] = 'square' 571 del self.data['class']
572 573 574
575 -class TriggerIn(AnyType):
576
577 - def __init__(self):
578 AnyType.__init__(self) 579 self.data['name'] = 'triggerIn' 580 self.data['color'] = 'orange' 581 self.data['shape'] = 'square' 582 del self.data['class']
583 584 585
586 -class TkColorType(AnyType):
587
588 - def __init__(self):
589 AnyType.__init__(self) 590 self.data['name'] = 'tkcolor' 591 self.data['color'] = 'orange' 592 self.data['shape'] = 'square' 593 del self.data['class']
594
595 - def validate(self, data):
596 import Tkinter 597 try: 598 Tkinter._default_root.winfo_rgb(data) 599 return True 600 finally: 601 return False
602 603 604
605 -class TypeManager:
606 """Port type object manager 607 608 This object is used to register port type instances which are associated with 609 port. new types can be registered by passing an instance of port type object 610 to the .addType(instance) method. 611 612 The .portTypeInstances dictionary provides a mapping between the a name used 613 to describe the data acceptable for a port and an instance of a subclass of 614 AnyArrayType. This name can be 615 616 The .reverseLookUp dictionary is used to obtain a port type from the class of 617 and object. This is used top propagate data types to ports that are mutatable 618 """ 619
620 - def __init__(self):
621 622 self.portTypeInstances = {} # key: name+datashape, value: instance 623 self.reverseLookUp = {} # key:class, value:typeObject 624 625 self.addType( AnyArrayType() ) 626 627 # basic types 628 self.addType( FloatType() ) 629 self.addType( IntType() ) 630 #self.addType( ObjectType() ) 631 632 self.addType( BooleanType() ) 633 self.addType( StringType() ) 634 # for backward compatibility: 635 self.portTypeInstances['str'] = self.portTypeInstances['string'] 636 637 # synonyms 638 self.addSynonym('coord2', 'float', '(2)', 639 color='green', shape='oval') 640 self.addSynonym('coord3', 'float', '(3)', 641 color='green', shape='rect') 642 self.addSynonym('normal3', 'float', '(3)', 643 color='blue', shape='rect') 644 self.addSynonym('colorfloat3or4', 'float', '(>=3 and <=4)', 645 color='orange', shape='rect') 646 self.addSynonym('instancemat', 'float', '(4,4)', 647 color='cyan', shape='rect') 648 self.addSynonym('indice2', 'int', '(2)', 649 color='purple', shape='rect') 650 self.addSynonym('indice2+', 'int', '(>=2)', 651 color='purple', shape='rect') 652 self.addSynonym('indice3or4', 'int', '(>=3 and <=4)', 653 color='purple', shape='rect') 654 655 self.addSynonym('2Darray', 'float', '(>0,>0)', color='cyan') 656 657 self.addSynonym('colorRGB', existingTypeName='colorfloat3or4') 658 self.addSynonym('colorsRGB', existingTypeName='colorRGB',datashape='(0)') 659 self.addSynonym('coordinates3D', existingTypeName='coord3',datashape='(0)') 660 self.addSynonym('faceIndices', existingTypeName='indice3or4',datashape='(0)') 661 self.addSynonym('normals3D', existingTypeName='normal3',datashape='(0)') 662 663 self.addType( AnyType() ) 664 self.addType( DictType() ) 665 self.addType( ListType() ) 666 self.addType( TkColorType() ) 667 self.addType( TupleType() ) 668 self.addType( ArrayType() ) 669 self.addType( NumericArrayType() ) 670 self.addType( VectorType() ) 671 self.addType( TriggerIn() ) 672 self.addType( TriggerOut() )
673 674
675 - def addSynonym(self, synonymName, existingTypeName=None, datashape=None, 676 color=None, shape=None, width=None, height=None):
677 """ method to create synonym types 678 synonymName: can be an existing name with a diferent datashape: 679 (existingTypeName must be None, and the basename 'coord3' must be registered) 680 self.addSynonym('coord3(3,4)') 681 existingTypeName: must be a registered name 682 (it can be datatshaped, if it is already registered like that) 683 self.addSynonym('coordinates3D', existingTypeName='coord3',datashape='(3,4)') 684 self.addSynonym('coordinates3D', existingTypeName='coord3(4)',datashape='(3)') 685 self.addSynonym('coordinates3D', existingTypeName='coord3(3,4)') 686 """ 687 if existingTypeName is None: 688 assert datashape is None 689 lSplitName = synonymName.split('(') 690 existingTypeName = lSplitName[0] 691 if len(lSplitName) == 2: 692 datashape = '(' + lSplitName[1] 693 basicInstance = self.portTypeInstances[existingTypeName] 694 innerDatashape = basicInstance['datashape'] 695 if innerDatashape is not None: 696 if datashape is None: 697 datashape = innerDatashape 698 else: 699 innerDatashape = innerDatashape.split('(')[1] 700 datashape = datashape.split(')')[0] 701 datashape = datashape + ',' + innerDatashape 702 if color is None: 703 color = basicInstance['color'] 704 if shape is None: 705 shape = basicInstance['shape'] 706 if width is None: 707 width = basicInstance['width'] 708 if height is None: 709 if shape == 'circle' or shape == 'square': 710 height = width 711 else: 712 height = 2 * width / 3 713 instance = basicInstance.__class__( 714 name=synonymName, datashape=datashape, 715 color=color, shape=shape, width=width, height=height) 716 self.addType( instance )
717 718
719 - def getSynonymDict(self, synonymName):
720 lDict = {} 721 typeInstance = self.portTypeInstances[synonymName] 722 lDict['existingTypeName'] = typeInstance.__class__()['name'] 723 if lDict['existingTypeName'] == synonymName: 724 return None 725 lDict['synonymName'] = synonymName 726 lDict['datashape'] = typeInstance['datashape'] 727 lDict['color'] = typeInstance['color'] 728 lDict['shape'] = typeInstance['shape'] 729 lDict['width'] = typeInstance['width'] 730 lDict['height'] = typeInstance['height'] 731 return lDict
732 733
734 - def addSynonymDict(self, aDict):
735 if aDict.has_key('existingTypeName') is False: 736 aDict['existingTypeName'] = None 737 if aDict.has_key('datashape') is False: 738 aDict['datashape'] = None 739 if aDict.has_key('color') is False: 740 aDict['color'] = None 741 if aDict.has_key('shape') is False: 742 aDict['shape'] = None 743 if aDict.has_key('width') is False: 744 aDict['width'] = None 745 if aDict.has_key('height') is False: 746 aDict['height'] = None 747 748 self.addSynonym(aDict['synonymName'], 749 existingTypeName=aDict['existingTypeName'], 750 datashape=aDict['datashape'], 751 color=aDict['color'], shape=aDict['shape'], 752 width=aDict['width'], height=aDict['height'])
753 754
755 - def addType(self, dtypeinstance):
756 """register a port type instance 757 """ 758 #print "addType dtypeinstance", dtypeinstance['name'], dtypeinstance['datashape'] 759 #import pdb;pdb.set_trace() 760 761 if isinstance(dtypeinstance, AnyType) or \ 762 isinstance(dtypeinstance, AnyArrayType): 763 764 # we reduce dtypeinstance to its base class name 765 splittype = dtypeinstance['name'].split('(') 766 basetypename = splittype[0] 767 768 if dtypeinstance['datashape'] is not None: 769 if dtypeinstance['name'].endswith(dtypeinstance['datashape']): 770 # make sure the base type exists 771 if self.portTypeInstances.has_key(basetypename) is None: 772 msg = 'Warning: base datatype '+basetypename 773 msg += ' not found in types table when adding %s'%str(dtypeinstance) 774 warnings.warn(msg) 775 return 776 storagename = dtypeinstance['name'] 777 else: 778 storagename = basetypename 779 780 if self.portTypeInstances.has_key(storagename): 781 if isinstance(dtypeinstance, AnyType): 782 if not ( \ 783 isinstance(self.portTypeInstances[storagename], AnyType) \ 784 and \ 785 (dtypeinstance.data == self.portTypeInstances[storagename].data) \ 786 ): 787 msg = 'Warning! datatype '+storagename+' already registered differently' 788 warnings.warn(msg) 789 return 790 elif isinstance(dtypeinstance, AnyArrayType): 791 if not ( \ 792 isinstance(self.portTypeInstances[storagename], AnyArrayType) \ 793 and \ 794 (dtypeinstance == self.portTypeInstances[storagename]) \ 795 ): 796 msg = 'Warning! datatype '+storagename+' already registered differently' 797 warnings.warn(msg) 798 return 799 800 self.portTypeInstances[storagename] = dtypeinstance 801 802 if dtypeinstance.has_key('class'): 803 if not self.reverseLookUp.has_key(dtypeinstance['class']): 804 self.reverseLookUp[dtypeinstance['class']] = dtypeinstance 805 806 else: 807 raise RuntimeError('bad dtypeinstance argument')
808 809
810 - def getType(self, fullName):
811 #print "getType fullName", fullName 812 #import traceback;traceback.print_stack() 813 #import pdb;pdb.set_trace() 814 splittype = fullName.split('(') 815 typename = splittype[0] 816 datashape = None 817 if len(splittype)==2: 818 datashape = '(' + splittype[1] 819 820 if not self.portTypeInstances.has_key(typename): 821 msg = 'Warning: base datatype ' + typename 822 msg += ' not found in types table' 823 warnings.warn(msg) 824 #import traceback;traceback.print_stack() 825 return self.portTypeInstances['None'] 826 827 if self.portTypeInstances.has_key(fullName) is False: 828 # base class exist but not with this datashape, we add it 829 self.addSynonym(fullName, typename, datashape) 830 831 return self.portTypeInstances[fullName]
832 833 834
835 - def getTypeFromClass(self, klass):
836 """ return the data type object for types that can be looked up i.e. 837 have a class attribute """ 838 return self.reverseLookUp.get(klass, self.reverseLookUp.get(None))
839 840
841 - def get(self, key, default=None):
842 return self.portTypeInstances.get(key, default)
843