bpo-39549: reprlib.Repr uses a “fillvalue” attribute (GH-18343)

This commit is contained in:
Alexander Böhn 2021-09-22 16:45:58 -04:00 committed by GitHub
parent 36122e1814
commit 8c21941dda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 9 deletions

View file

@ -76,6 +76,14 @@ size limits for the representations of different object types, and methods
which format specific object types. which format specific object types.
.. attribute:: Repr.fillvalue
This string is displayed for recursive references. It defaults to
``...``.
.. versionadded:: 3.11
.. attribute:: Repr.maxlevel .. attribute:: Repr.maxlevel
Depth limit on the creation of recursive representations. The default is ``6``. Depth limit on the creation of recursive representations. The default is ``6``.

View file

@ -36,6 +36,7 @@ def recursive_repr(fillvalue='...'):
class Repr: class Repr:
def __init__(self): def __init__(self):
self.fillvalue = '...'
self.maxlevel = 6 self.maxlevel = 6
self.maxtuple = 6 self.maxtuple = 6
self.maxlist = 6 self.maxlist = 6
@ -64,14 +65,16 @@ class Repr:
def _repr_iterable(self, x, level, left, right, maxiter, trail=''): def _repr_iterable(self, x, level, left, right, maxiter, trail=''):
n = len(x) n = len(x)
if level <= 0 and n: if level <= 0 and n:
s = '...' s = self.fillvalue
else: else:
newlevel = level - 1 newlevel = level - 1
repr1 = self.repr1 repr1 = self.repr1
pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)] pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)]
if n > maxiter: pieces.append('...') if n > maxiter:
pieces.append(self.fillvalue)
s = ', '.join(pieces) s = ', '.join(pieces)
if n == 1 and trail: right = trail + right if n == 1 and trail:
right = trail + right
return '%s%s%s' % (left, s, right) return '%s%s%s' % (left, s, right)
def repr_tuple(self, x, level): def repr_tuple(self, x, level):
@ -104,8 +107,10 @@ class Repr:
def repr_dict(self, x, level): def repr_dict(self, x, level):
n = len(x) n = len(x)
if n == 0: return '{}' if n == 0:
if level <= 0: return '{...}' return '{}'
if level <= 0:
return '{' + self.fillvalue + '}'
newlevel = level - 1 newlevel = level - 1
repr1 = self.repr1 repr1 = self.repr1
pieces = [] pieces = []
@ -113,7 +118,8 @@ class Repr:
keyrepr = repr1(key, newlevel) keyrepr = repr1(key, newlevel)
valrepr = repr1(x[key], newlevel) valrepr = repr1(x[key], newlevel)
pieces.append('%s: %s' % (keyrepr, valrepr)) pieces.append('%s: %s' % (keyrepr, valrepr))
if n > self.maxdict: pieces.append('...') if n > self.maxdict:
pieces.append(self.fillvalue)
s = ', '.join(pieces) s = ', '.join(pieces)
return '{%s}' % (s,) return '{%s}' % (s,)
@ -123,7 +129,7 @@ class Repr:
i = max(0, (self.maxstring-3)//2) i = max(0, (self.maxstring-3)//2)
j = max(0, self.maxstring-3-i) j = max(0, self.maxstring-3-i)
s = builtins.repr(x[:i] + x[len(x)-j:]) s = builtins.repr(x[:i] + x[len(x)-j:])
s = s[:i] + '...' + s[len(s)-j:] s = s[:i] + self.fillvalue + s[len(s)-j:]
return s return s
def repr_int(self, x, level): def repr_int(self, x, level):
@ -131,7 +137,7 @@ class Repr:
if len(s) > self.maxlong: if len(s) > self.maxlong:
i = max(0, (self.maxlong-3)//2) i = max(0, (self.maxlong-3)//2)
j = max(0, self.maxlong-3-i) j = max(0, self.maxlong-3-i)
s = s[:i] + '...' + s[len(s)-j:] s = s[:i] + self.fillvalue + s[len(s)-j:]
return s return s
def repr_instance(self, x, level): def repr_instance(self, x, level):
@ -144,7 +150,7 @@ class Repr:
if len(s) > self.maxother: if len(s) > self.maxother:
i = max(0, (self.maxother-3)//2) i = max(0, (self.maxother-3)//2)
j = max(0, self.maxother-3-i) j = max(0, self.maxother-3-i)
s = s[:i] + '...' + s[len(s)-j:] s = s[:i] + self.fillvalue + s[len(s)-j:]
return s return s

View file

@ -51,6 +51,13 @@ class ReprTests(unittest.TestCase):
expected = repr(t3)[:-2] + "...)" expected = repr(t3)[:-2] + "...)"
eq(r2.repr(t3), expected) eq(r2.repr(t3), expected)
# modified fillvalue:
r3 = Repr()
r3.fillvalue = '+++'
r3.maxtuple = 2
expected = repr(t3)[:-2] + "+++)"
eq(r3.repr(t3), expected)
def test_container(self): def test_container(self):
from array import array from array import array
from collections import deque from collections import deque

View file

@ -0,0 +1,4 @@
Whereas the code for reprlib.Repr had previously used a hardcoded string
value of '...', this PR updates it to use of a “fillvalue” attribute, whose
value defaults to '...' and can be reset in either individual reprlib.Repr
instances or in subclasses thereof.