@@ -502,33 +502,53 @@ def update(self):
502502
503503
504504SIMPLE_TYPES = (
505- types .NoneType ,
506- types .IntType ,
507- types .LongType ,
508- types .FloatType ,
509- types .ComplexType ,
510- types .StringType
505+ type (None ),
506+ int ,
507+ long ,
508+ float ,
509+ complex ,
510+ str ,
511+ unicode ,
511512)
512513
513- INDEXING_TYPES = (
514- types .TupleType ,
515- types .ListType ,
516- types .DictionaryType
517- )
514+ def get_ivars (obj ):
515+ """Return a list the names of all (potential) instance variables."""
516+ # __mro__ recipe from Guido
517+ slots = {}
518+ # old-style C objects
519+ if hasattr (obj , "__members__" ):
520+ for name in obj .__members__ :
521+ slots [name ] = None
522+ if hasattr (obj , "__methods__" ):
523+ for name in obj .__methods__ :
524+ slots [name ] = None
525+ # generic type
526+ if hasattr (obj , "__dict__" ):
527+ slots .update (obj .__dict__ )
528+ cls = type (obj )
529+ if hasattr (cls , "__mro__" ):
530+ # new-style class, use descriptors
531+ for base in cls .__mro__ :
532+ for name , value in base .__dict__ .items ():
533+ # XXX using callable() is a heuristic which isn't 100%
534+ # foolproof.
535+ if hasattr (value , "__get__" ) and not callable (value ):
536+ slots [name ] = None
537+ if "__dict__" in slots :
538+ del slots ["__dict__" ]
539+ slots = slots .keys ()
540+ slots .sort ()
541+ return slots
518542
519543def unpack_object (object , indent = 0 ):
520544 tp = type (object )
521- if tp in SIMPLE_TYPES and tp is not types . NoneType :
545+ if isinstance ( object , SIMPLE_TYPES ) and object is not None :
522546 raise TypeError , "can't browse simple type: %s" % tp .__name__
523- elif tp == types . DictionaryType :
547+ elif isinstance ( object , dict ) :
524548 return unpack_dict (object , indent )
525- elif tp in ( types . TupleType , types . ListType ):
549+ elif isinstance ( object , ( tuple , list ) ):
526550 return unpack_sequence (object , indent )
527- elif tp == types .InstanceType :
528- return unpack_instance (object , indent )
529- elif tp == types .ClassType :
530- return unpack_class (object , indent )
531- elif tp == types .ModuleType :
551+ elif isinstance (object , types .ModuleType ):
532552 return unpack_dict (object .__dict__ , indent )
533553 else :
534554 return unpack_other (object , indent )
@@ -555,23 +575,15 @@ def unpack_class(clss, indent = 0):
555575 return pack_items (items , indent )
556576
557577def unpack_other (object , indent = 0 ):
558- attrs = []
559- if hasattr (object , '__members__' ):
560- attrs = attrs + object .__members__
561- if hasattr (object , '__methods__' ):
562- attrs = attrs + object .__methods__
563- if hasattr (object , '__dict__' ):
564- attrs = attrs + object .__dict__ .keys ()
565- if hasattr (object , '__slots__' ):
566- # XXX??
567- attrs = attrs + object .__slots__
568- if hasattr (object , "__class__" ) and "__class__" not in attrs :
569- attrs .append ("__class__" )
570- if hasattr (object , "__doc__" ) and "__doc__" not in attrs :
571- attrs .append ("__doc__" )
578+ attrs = get_ivars (object )
572579 items = []
573580 for attr in attrs :
574- items .append ((attr , getattr (object , attr )))
581+ try :
582+ value = getattr (object , attr )
583+ except :
584+ pass
585+ else :
586+ items .append ((attr , value ))
575587 return pack_items (items , indent )
576588
577589def pack_items (items , indent = 0 ):
0 commit comments