From 6685a61413dd30204a5bd0f70e6bd891a29557ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20B=C3=B6hn?= Date: Mon, 3 Feb 2020 21:11:28 -0500 Subject: [PATCH 1/2] =?UTF-8?q?bpo-39549:=20reprlib.Repr=20uses=20a=20?= =?UTF-8?q?=E2=80=9Cfillvalue=E2=80=9D=20attribute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. A new assert has been added to `test_reprlib.py` to verify the new attributes’ functionality. --- Lib/reprlib.py | 24 ++++++++++++------- Lib/test/test_reprlib.py | 7 ++++++ .../2020-02-03-21-18-31.bpo-39549.l4a8uH.rst | 4 ++++ 3 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-02-03-21-18-31.bpo-39549.l4a8uH.rst diff --git a/Lib/reprlib.py b/Lib/reprlib.py index 616b3439b5de30..f3518df105e418 100644 --- a/Lib/reprlib.py +++ b/Lib/reprlib.py @@ -36,6 +36,7 @@ def wrapper(self): class Repr: def __init__(self): + self.fillvalue = '...' self.maxlevel = 6 self.maxtuple = 6 self.maxlist = 6 @@ -64,14 +65,16 @@ def repr1(self, x, level): def _repr_iterable(self, x, level, left, right, maxiter, trail=''): n = len(x) if level <= 0 and n: - s = '...' + s = self.fillvalue else: newlevel = level - 1 repr1 = self.repr1 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) - if n == 1 and trail: right = trail + right + if n == 1 and trail: + right = trail + right return '%s%s%s' % (left, s, right) def repr_tuple(self, x, level): @@ -104,8 +107,10 @@ def repr_deque(self, x, level): def repr_dict(self, x, level): n = len(x) - if n == 0: return '{}' - if level <= 0: return '{...}' + if n == 0: + return '{}' + if level <= 0: + return '{' + self.fillvalue + '}' newlevel = level - 1 repr1 = self.repr1 pieces = [] @@ -113,7 +118,8 @@ def repr_dict(self, x, level): keyrepr = repr1(key, newlevel) valrepr = repr1(x[key], newlevel) pieces.append('%s: %s' % (keyrepr, valrepr)) - if n > self.maxdict: pieces.append('...') + if n > self.maxdict: + pieces.append(self.fillvalue) s = ', '.join(pieces) return '{%s}' % (s,) @@ -123,7 +129,7 @@ def repr_str(self, x, level): i = max(0, (self.maxstring-3)//2) j = max(0, self.maxstring-3-i) 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 def repr_int(self, x, level): @@ -131,7 +137,7 @@ def repr_int(self, x, level): if len(s) > self.maxlong: i = max(0, (self.maxlong-3)//2) 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 def repr_instance(self, x, level): @@ -144,7 +150,7 @@ def repr_instance(self, x, level): if len(s) > self.maxother: i = max(0, (self.maxother-3)//2) 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 diff --git a/Lib/test/test_reprlib.py b/Lib/test/test_reprlib.py index 0555b71bbf21af..aa326399ab2247 100644 --- a/Lib/test/test_reprlib.py +++ b/Lib/test/test_reprlib.py @@ -51,6 +51,13 @@ def test_tuple(self): expected = repr(t3)[:-2] + "...)" 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): from array import array from collections import deque diff --git a/Misc/NEWS.d/next/Library/2020-02-03-21-18-31.bpo-39549.l4a8uH.rst b/Misc/NEWS.d/next/Library/2020-02-03-21-18-31.bpo-39549.l4a8uH.rst new file mode 100644 index 00000000000000..91d63a96763cee --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-03-21-18-31.bpo-39549.l4a8uH.rst @@ -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. From fe900355fff2ab729f2185c975210691b05e7c7e Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Tue, 21 Sep 2021 14:25:17 -0500 Subject: [PATCH 2/2] Add to the main docs --- Doc/library/reprlib.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Doc/library/reprlib.rst b/Doc/library/reprlib.rst index 1a0c1b0dcd1aa9..4b37c5ba60f4e6 100644 --- a/Doc/library/reprlib.rst +++ b/Doc/library/reprlib.rst @@ -76,6 +76,14 @@ size limits for the representations of different object types, and methods which format specific object types. +.. attribute:: Repr.fillvalue + + This string is displayed for recursive references. It defaults to + ``...``. + + .. versionadded:: 3.11 + + .. attribute:: Repr.maxlevel Depth limit on the creation of recursive representations. The default is ``6``.