xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/reprlib.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
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