def describe_object_with_dict_details(o): sl = [] sl.append(str(type(o))) if isinstance(o, types.FunctionType): try: sl.append(str(o.func_name)) except: pass elif isinstance(o, types.MethodType): try: sl.append(str(o.im_func.func_name)) except: pass try: sl.append(str(len(o))) except: pass if isinstance(o, dict) and o: sl.append('-') nd = dictutil.NumDict() for k, v in o.iteritems(): nd.inc(( describe_object(k), describe_object(v), )) k, v = nd.item_with_largest_value() sl.append("-") iterator = o.iteritems() k, v = iterator.next() sl.append(describe_object(k)) sl.append(":") sl.append(describe_object(v)) return ''.join(sl)
class NummedObj(object): """ This is useful for nicer debug printouts. Instead of objects of the same class being distinguished from one another by their memory address, they each get a unique number, which can be read as "the first object of this class", "the second object of this class", etc. This is especially useful because separate runs of a program will yield identical debug output, (assuming that the objects get created in the same order in each run). This makes it possible to diff outputs from separate runs to see what changed, without having to ignore a difference on every line due to different memory addresses of objects. """ objnums = dictutil.NumDict() # key: class names, value: highest used object number def __init__(self, klass=None): """ @param klass: in which class are you counted? If default value of `None', then self.__class__ will be used. """ if klass is None: klass = self.__class__ self._classname = klass.__name__ NummedObj.objnums.inc(self._classname) self._objid = NummedObj.objnums[self._classname] def __repr__(self): return "<%s #%d>" % (self._classname, self._objid,) def __lt__(self, other): return (self._objid, self._classname,) < (other._objid, other._classname,) def __le__(self, other): return (self._objid, self._classname,) <= (other._objid, other._classname,) def __eq__(self, other): return (self._objid, self._classname,) == (other._objid, other._classname,) def __ne__(self, other): return (self._objid, self._classname,) != (other._objid, other._classname,) def __gt__(self, other): return (self._objid, self._classname,) > (other._objid, other._classname,) def __ge__(self, other): return (self._objid, self._classname,) >= (other._objid, other._classname,) def __hash__(self): return id(self)
def describe_all_objects(): import dictutil d = dictutil.NumDict() for o in get_all_objects(): d.inc(describe_object(o)) return d