1*cda5da8dSAndroid Build Coastguard Worker"""Redo the builtin repr() (representation) but with limits on most sizes.""" 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard Worker__all__ = ["Repr", "repr", "recursive_repr"] 4*cda5da8dSAndroid Build Coastguard Worker 5*cda5da8dSAndroid Build Coastguard Workerimport builtins 6*cda5da8dSAndroid Build Coastguard Workerfrom itertools import islice 7*cda5da8dSAndroid Build Coastguard Workerfrom _thread import get_ident 8*cda5da8dSAndroid Build Coastguard Worker 9*cda5da8dSAndroid Build Coastguard Workerdef recursive_repr(fillvalue='...'): 10*cda5da8dSAndroid Build Coastguard Worker 'Decorator to make a repr function return fillvalue for a recursive call' 11*cda5da8dSAndroid Build Coastguard Worker 12*cda5da8dSAndroid Build Coastguard Worker def decorating_function(user_function): 13*cda5da8dSAndroid Build Coastguard Worker repr_running = set() 14*cda5da8dSAndroid Build Coastguard Worker 15*cda5da8dSAndroid Build Coastguard Worker def wrapper(self): 16*cda5da8dSAndroid Build Coastguard Worker key = id(self), get_ident() 17*cda5da8dSAndroid Build Coastguard Worker if key in repr_running: 18*cda5da8dSAndroid Build Coastguard Worker return fillvalue 19*cda5da8dSAndroid Build Coastguard Worker repr_running.add(key) 20*cda5da8dSAndroid Build Coastguard Worker try: 21*cda5da8dSAndroid Build Coastguard Worker result = user_function(self) 22*cda5da8dSAndroid Build Coastguard Worker finally: 23*cda5da8dSAndroid Build Coastguard Worker repr_running.discard(key) 24*cda5da8dSAndroid Build Coastguard Worker return result 25*cda5da8dSAndroid Build Coastguard Worker 26*cda5da8dSAndroid Build Coastguard Worker # Can't use functools.wraps() here because of bootstrap issues 27*cda5da8dSAndroid Build Coastguard Worker wrapper.__module__ = getattr(user_function, '__module__') 28*cda5da8dSAndroid Build Coastguard Worker wrapper.__doc__ = getattr(user_function, '__doc__') 29*cda5da8dSAndroid Build Coastguard Worker wrapper.__name__ = getattr(user_function, '__name__') 30*cda5da8dSAndroid Build Coastguard Worker wrapper.__qualname__ = getattr(user_function, '__qualname__') 31*cda5da8dSAndroid Build Coastguard Worker wrapper.__annotations__ = getattr(user_function, '__annotations__', {}) 32*cda5da8dSAndroid Build Coastguard Worker return wrapper 33*cda5da8dSAndroid Build Coastguard Worker 34*cda5da8dSAndroid Build Coastguard Worker return decorating_function 35*cda5da8dSAndroid Build Coastguard Worker 36*cda5da8dSAndroid Build Coastguard Workerclass Repr: 37*cda5da8dSAndroid Build Coastguard Worker 38*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 39*cda5da8dSAndroid Build Coastguard Worker self.fillvalue = '...' 40*cda5da8dSAndroid Build Coastguard Worker self.maxlevel = 6 41*cda5da8dSAndroid Build Coastguard Worker self.maxtuple = 6 42*cda5da8dSAndroid Build Coastguard Worker self.maxlist = 6 43*cda5da8dSAndroid Build Coastguard Worker self.maxarray = 5 44*cda5da8dSAndroid Build Coastguard Worker self.maxdict = 4 45*cda5da8dSAndroid Build Coastguard Worker self.maxset = 6 46*cda5da8dSAndroid Build Coastguard Worker self.maxfrozenset = 6 47*cda5da8dSAndroid Build Coastguard Worker self.maxdeque = 6 48*cda5da8dSAndroid Build Coastguard Worker self.maxstring = 30 49*cda5da8dSAndroid Build Coastguard Worker self.maxlong = 40 50*cda5da8dSAndroid Build Coastguard Worker self.maxother = 30 51*cda5da8dSAndroid Build Coastguard Worker 52*cda5da8dSAndroid Build Coastguard Worker def repr(self, x): 53*cda5da8dSAndroid Build Coastguard Worker return self.repr1(x, self.maxlevel) 54*cda5da8dSAndroid Build Coastguard Worker 55*cda5da8dSAndroid Build Coastguard Worker def repr1(self, x, level): 56*cda5da8dSAndroid Build Coastguard Worker typename = type(x).__name__ 57*cda5da8dSAndroid Build Coastguard Worker if ' ' in typename: 58*cda5da8dSAndroid Build Coastguard Worker parts = typename.split() 59*cda5da8dSAndroid Build Coastguard Worker typename = '_'.join(parts) 60*cda5da8dSAndroid Build Coastguard Worker if hasattr(self, 'repr_' + typename): 61*cda5da8dSAndroid Build Coastguard Worker return getattr(self, 'repr_' + typename)(x, level) 62*cda5da8dSAndroid Build Coastguard Worker else: 63*cda5da8dSAndroid Build Coastguard Worker return self.repr_instance(x, level) 64*cda5da8dSAndroid Build Coastguard Worker 65*cda5da8dSAndroid Build Coastguard Worker def _repr_iterable(self, x, level, left, right, maxiter, trail=''): 66*cda5da8dSAndroid Build Coastguard Worker n = len(x) 67*cda5da8dSAndroid Build Coastguard Worker if level <= 0 and n: 68*cda5da8dSAndroid Build Coastguard Worker s = self.fillvalue 69*cda5da8dSAndroid Build Coastguard Worker else: 70*cda5da8dSAndroid Build Coastguard Worker newlevel = level - 1 71*cda5da8dSAndroid Build Coastguard Worker repr1 = self.repr1 72*cda5da8dSAndroid Build Coastguard Worker pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)] 73*cda5da8dSAndroid Build Coastguard Worker if n > maxiter: 74*cda5da8dSAndroid Build Coastguard Worker pieces.append(self.fillvalue) 75*cda5da8dSAndroid Build Coastguard Worker s = ', '.join(pieces) 76*cda5da8dSAndroid Build Coastguard Worker if n == 1 and trail: 77*cda5da8dSAndroid Build Coastguard Worker right = trail + right 78*cda5da8dSAndroid Build Coastguard Worker return '%s%s%s' % (left, s, right) 79*cda5da8dSAndroid Build Coastguard Worker 80*cda5da8dSAndroid Build Coastguard Worker def repr_tuple(self, x, level): 81*cda5da8dSAndroid Build Coastguard Worker return self._repr_iterable(x, level, '(', ')', self.maxtuple, ',') 82*cda5da8dSAndroid Build Coastguard Worker 83*cda5da8dSAndroid Build Coastguard Worker def repr_list(self, x, level): 84*cda5da8dSAndroid Build Coastguard Worker return self._repr_iterable(x, level, '[', ']', self.maxlist) 85*cda5da8dSAndroid Build Coastguard Worker 86*cda5da8dSAndroid Build Coastguard Worker def repr_array(self, x, level): 87*cda5da8dSAndroid Build Coastguard Worker if not x: 88*cda5da8dSAndroid Build Coastguard Worker return "array('%s')" % x.typecode 89*cda5da8dSAndroid Build Coastguard Worker header = "array('%s', [" % x.typecode 90*cda5da8dSAndroid Build Coastguard Worker return self._repr_iterable(x, level, header, '])', self.maxarray) 91*cda5da8dSAndroid Build Coastguard Worker 92*cda5da8dSAndroid Build Coastguard Worker def repr_set(self, x, level): 93*cda5da8dSAndroid Build Coastguard Worker if not x: 94*cda5da8dSAndroid Build Coastguard Worker return 'set()' 95*cda5da8dSAndroid Build Coastguard Worker x = _possibly_sorted(x) 96*cda5da8dSAndroid Build Coastguard Worker return self._repr_iterable(x, level, '{', '}', self.maxset) 97*cda5da8dSAndroid Build Coastguard Worker 98*cda5da8dSAndroid Build Coastguard Worker def repr_frozenset(self, x, level): 99*cda5da8dSAndroid Build Coastguard Worker if not x: 100*cda5da8dSAndroid Build Coastguard Worker return 'frozenset()' 101*cda5da8dSAndroid Build Coastguard Worker x = _possibly_sorted(x) 102*cda5da8dSAndroid Build Coastguard Worker return self._repr_iterable(x, level, 'frozenset({', '})', 103*cda5da8dSAndroid Build Coastguard Worker self.maxfrozenset) 104*cda5da8dSAndroid Build Coastguard Worker 105*cda5da8dSAndroid Build Coastguard Worker def repr_deque(self, x, level): 106*cda5da8dSAndroid Build Coastguard Worker return self._repr_iterable(x, level, 'deque([', '])', self.maxdeque) 107*cda5da8dSAndroid Build Coastguard Worker 108*cda5da8dSAndroid Build Coastguard Worker def repr_dict(self, x, level): 109*cda5da8dSAndroid Build Coastguard Worker n = len(x) 110*cda5da8dSAndroid Build Coastguard Worker if n == 0: 111*cda5da8dSAndroid Build Coastguard Worker return '{}' 112*cda5da8dSAndroid Build Coastguard Worker if level <= 0: 113*cda5da8dSAndroid Build Coastguard Worker return '{' + self.fillvalue + '}' 114*cda5da8dSAndroid Build Coastguard Worker newlevel = level - 1 115*cda5da8dSAndroid Build Coastguard Worker repr1 = self.repr1 116*cda5da8dSAndroid Build Coastguard Worker pieces = [] 117*cda5da8dSAndroid Build Coastguard Worker for key in islice(_possibly_sorted(x), self.maxdict): 118*cda5da8dSAndroid Build Coastguard Worker keyrepr = repr1(key, newlevel) 119*cda5da8dSAndroid Build Coastguard Worker valrepr = repr1(x[key], newlevel) 120*cda5da8dSAndroid Build Coastguard Worker pieces.append('%s: %s' % (keyrepr, valrepr)) 121*cda5da8dSAndroid Build Coastguard Worker if n > self.maxdict: 122*cda5da8dSAndroid Build Coastguard Worker pieces.append(self.fillvalue) 123*cda5da8dSAndroid Build Coastguard Worker s = ', '.join(pieces) 124*cda5da8dSAndroid Build Coastguard Worker return '{%s}' % (s,) 125*cda5da8dSAndroid Build Coastguard Worker 126*cda5da8dSAndroid Build Coastguard Worker def repr_str(self, x, level): 127*cda5da8dSAndroid Build Coastguard Worker s = builtins.repr(x[:self.maxstring]) 128*cda5da8dSAndroid Build Coastguard Worker if len(s) > self.maxstring: 129*cda5da8dSAndroid Build Coastguard Worker i = max(0, (self.maxstring-3)//2) 130*cda5da8dSAndroid Build Coastguard Worker j = max(0, self.maxstring-3-i) 131*cda5da8dSAndroid Build Coastguard Worker s = builtins.repr(x[:i] + x[len(x)-j:]) 132*cda5da8dSAndroid Build Coastguard Worker s = s[:i] + self.fillvalue + s[len(s)-j:] 133*cda5da8dSAndroid Build Coastguard Worker return s 134*cda5da8dSAndroid Build Coastguard Worker 135*cda5da8dSAndroid Build Coastguard Worker def repr_int(self, x, level): 136*cda5da8dSAndroid Build Coastguard Worker s = builtins.repr(x) # XXX Hope this isn't too slow... 137*cda5da8dSAndroid Build Coastguard Worker if len(s) > self.maxlong: 138*cda5da8dSAndroid Build Coastguard Worker i = max(0, (self.maxlong-3)//2) 139*cda5da8dSAndroid Build Coastguard Worker j = max(0, self.maxlong-3-i) 140*cda5da8dSAndroid Build Coastguard Worker s = s[:i] + self.fillvalue + s[len(s)-j:] 141*cda5da8dSAndroid Build Coastguard Worker return s 142*cda5da8dSAndroid Build Coastguard Worker 143*cda5da8dSAndroid Build Coastguard Worker def repr_instance(self, x, level): 144*cda5da8dSAndroid Build Coastguard Worker try: 145*cda5da8dSAndroid Build Coastguard Worker s = builtins.repr(x) 146*cda5da8dSAndroid Build Coastguard Worker # Bugs in x.__repr__() can cause arbitrary 147*cda5da8dSAndroid Build Coastguard Worker # exceptions -- then make up something 148*cda5da8dSAndroid Build Coastguard Worker except Exception: 149*cda5da8dSAndroid Build Coastguard Worker return '<%s instance at %#x>' % (x.__class__.__name__, id(x)) 150*cda5da8dSAndroid Build Coastguard Worker if len(s) > self.maxother: 151*cda5da8dSAndroid Build Coastguard Worker i = max(0, (self.maxother-3)//2) 152*cda5da8dSAndroid Build Coastguard Worker j = max(0, self.maxother-3-i) 153*cda5da8dSAndroid Build Coastguard Worker s = s[:i] + self.fillvalue + s[len(s)-j:] 154*cda5da8dSAndroid Build Coastguard Worker return s 155*cda5da8dSAndroid Build Coastguard Worker 156*cda5da8dSAndroid Build Coastguard Worker 157*cda5da8dSAndroid Build Coastguard Workerdef _possibly_sorted(x): 158*cda5da8dSAndroid Build Coastguard Worker # Since not all sequences of items can be sorted and comparison 159*cda5da8dSAndroid Build Coastguard Worker # functions may raise arbitrary exceptions, return an unsorted 160*cda5da8dSAndroid Build Coastguard Worker # sequence in that case. 161*cda5da8dSAndroid Build Coastguard Worker try: 162*cda5da8dSAndroid Build Coastguard Worker return sorted(x) 163*cda5da8dSAndroid Build Coastguard Worker except Exception: 164*cda5da8dSAndroid Build Coastguard Worker return list(x) 165*cda5da8dSAndroid Build Coastguard Worker 166*cda5da8dSAndroid Build Coastguard WorkeraRepr = Repr() 167*cda5da8dSAndroid Build Coastguard Workerrepr = aRepr.repr 168