From d88618ac690845a32033525c7b34765b93cd7159 Mon Sep 17 00:00:00 2001 From: Ben Bonenfant Date: Sun, 25 Oct 2020 15:46:19 -0400 Subject: [PATCH 1/5] bpo-27495: Make pprint.pformat always order sets --- Lib/pprint.py | 31 +++++++++++++++++++++++++++++++ Lib/test/test_pprint.py | 18 ++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/Lib/pprint.py b/Lib/pprint.py index 213998e3491ef7..0b70c2284b936b 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -587,6 +587,37 @@ def _safe_repr(object, context, maxlevels, level, sort_dicts): del context[objid] return format % ", ".join(components), readable, recursive + if (issubclass(typ, set) and r is set.__repr__) or \ + (issubclass(typ, frozenset) and r is frozenset.__repr__): + if not object: + return repr(object), True, False + if typ is set: + format = "{%s}" + else: + format = typ.__name__ + "({%s})" + objid = id(object) + if maxlevels and level >= maxlevels: + return "{...}", False, objid in context + if objid in context: + return _recursion(object), False, True + context[objid] = 1 + readable = True + recursive = False + components = [] + append = components.append + level += 1 + saferepr = _safe_repr + items = sorted(object, key=_safe_key) + for item in items: + orepr, oreadable, orecur = saferepr(item, context, maxlevels, level, sort_dicts) + append("%s" % orepr) + if not oreadable: + readable = False + if orecur: + recursive = True + del context[objid] + return format % ", ".join(components), readable, recursive + rep = repr(object) return rep, (rep and not rep.startswith('<')), False diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index 8ee18e8fef84f7..a868aba378e422 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -463,6 +463,9 @@ def test_subclassing(self): def test_set_reprs(self): self.assertEqual(pprint.pformat(set()), 'set()') self.assertEqual(pprint.pformat(set(range(3))), '{0, 1, 2}') + self.assertEqual(pprint.pformat(set([-1, 0, 1])), "{-1, 0, 1}") + self.assertEqual(pprint.pformat(set("0123")), "{'0', '1', '2', '3'}") + self.assertEqual(pprint.pformat(set("abcd")), "{'a', 'b', 'c', 'd'}") self.assertEqual(pprint.pformat(set(range(7)), width=20), '''\ {0, 1, @@ -471,6 +474,9 @@ def test_set_reprs(self): 4, 5, 6}''') + self.assertEqual(pprint.pformat(set2([-1, 0, 1])), "set2({-1, 0, 1})") + self.assertEqual(pprint.pformat(set2("0123")), "set2({'0', '1', '2', '3'})") + self.assertEqual(pprint.pformat(set2("abcd")), "set2({'a', 'b', 'c', 'd'})") self.assertEqual(pprint.pformat(set2(range(7)), width=20), '''\ set2({0, 1, @@ -485,6 +491,12 @@ def test_set_reprs(self): self.assertEqual(pprint.pformat(frozenset()), 'frozenset()') self.assertEqual(pprint.pformat(frozenset(range(3))), 'frozenset({0, 1, 2})') + self.assertEqual(pprint.pformat(frozenset([-1, 0, 1])), + "frozenset({-1, 0, 1})") + self.assertEqual(pprint.pformat(frozenset("0123")), + "frozenset({'0', '1', '2', '3'})") + self.assertEqual(pprint.pformat(frozenset("abcd")), + "frozenset({'a', 'b', 'c', 'd'})") self.assertEqual(pprint.pformat(frozenset(range(7)), width=20), '''\ frozenset({0, 1, @@ -493,6 +505,12 @@ def test_set_reprs(self): 4, 5, 6})''') + self.assertEqual(pprint.pformat(frozenset2([-1, 0, 1])), + "frozenset2({-1, 0, 1})") + self.assertEqual(pprint.pformat(frozenset2("0123")), + "frozenset2({'0', '1', '2', '3'})") + self.assertEqual(pprint.pformat(frozenset2("abcd")), + "frozenset2({'a', 'b', 'c', 'd'})") self.assertEqual(pprint.pformat(frozenset2(range(7)), width=20), '''\ frozenset2({0, 1, From f2cfad16eeeaba9a995b3bc15b0a55db6532db9f Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2020 14:20:59 +0000 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst diff --git a/Misc/NEWS.d/next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst b/Misc/NEWS.d/next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst new file mode 100644 index 00000000000000..c71fe6005b6aa2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst @@ -0,0 +1 @@ +Update the `pprint` module to always order the contents of `set` and `frozenset` objects. \ No newline at end of file From 99f799405f53baa42328ff558f3ce0a894c15408 Mon Sep 17 00:00:00 2001 From: Ben Bonenfant Date: Sat, 28 Nov 2020 11:22:51 -0500 Subject: [PATCH 3/5] Added name to Misc/ACKS. --- Misc/ACKS | 1 + 1 file changed, 1 insertion(+) diff --git a/Misc/ACKS b/Misc/ACKS index 253349017c5cdc..3741f5d8729fb1 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -193,6 +193,7 @@ Gawain Bolton Carl Friedrich Bolz-Tereick Forest Bond Gregory Bond +Ben Bonenfant Angelin Booz Médéric Boquien Matias Bordese From 63128b53ab115b024fb1037f7eb593bc752d4a0b Mon Sep 17 00:00:00 2001 From: Ben Bonenfant Date: Sat, 5 Dec 2020 13:43:41 -0500 Subject: [PATCH 4/5] Update Misc/NEWS.d/next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst Co-authored-by: Zackery Spytz --- .../next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst b/Misc/NEWS.d/next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst index c71fe6005b6aa2..d444cbdf9e2ebb 100644 --- a/Misc/NEWS.d/next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst +++ b/Misc/NEWS.d/next/Library/2020-10-26-14-20-58.bpo-27495.OWavSt.rst @@ -1 +1,2 @@ -Update the `pprint` module to always order the contents of `set` and `frozenset` objects. \ No newline at end of file +Update the :mod:`pprint` module to always order the contents of :class:`set` +and :class:`frozenset` objects. From cdcccc12748774300448f017dc4ac5d558af4432 Mon Sep 17 00:00:00 2001 From: Ben Bonenfant Date: Sat, 5 Dec 2020 13:44:04 -0500 Subject: [PATCH 5/5] Updates based upon requests from #22977 --- Lib/pprint.py | 53 +++++++++++++---------------------------- Lib/test/test_pprint.py | 6 +++-- 2 files changed, 21 insertions(+), 38 deletions(-) diff --git a/Lib/pprint.py b/Lib/pprint.py index 0115a42a70c3f2..5742b86c49de3b 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -556,17 +556,29 @@ def _safe_repr(self, object, context, maxlevels, level): return "{%s}" % ", ".join(components), readable, recursive if (issubclass(typ, list) and r is list.__repr__) or \ - (issubclass(typ, tuple) and r is tuple.__repr__): + (issubclass(typ, tuple) and r is tuple.__repr__) or \ + (issubclass(typ, set) and r is set.__repr__) or \ + (issubclass(typ, frozenset) and r is frozenset.__repr__): if issubclass(typ, list): if not object: return "[]", True, False format = "[%s]" - elif len(object) == 1: - format = "(%s,)" + elif issubclass(typ, tuple): + if len(object) == 1: + format = "(%s,)" + else: + if not object: + return "()", True, False + format = "(%s)" else: if not object: - return "()", True, False - format = "(%s)" + return repr(object), True, False + if typ is set: + format = "{%s}" + else: + format = typ.__name__ + "({%s})" + object = sorted(object, key=_safe_key) + objid = id(object) if maxlevels and level >= maxlevels: return format % "...", False, objid in context @@ -589,37 +601,6 @@ def _safe_repr(self, object, context, maxlevels, level): del context[objid] return format % ", ".join(components), readable, recursive - if (issubclass(typ, set) and r is set.__repr__) or \ - (issubclass(typ, frozenset) and r is frozenset.__repr__): - if not object: - return repr(object), True, False - if typ is set: - format = "{%s}" - else: - format = typ.__name__ + "({%s})" - objid = id(object) - if maxlevels and level >= maxlevels: - return "{...}", False, objid in context - if objid in context: - return _recursion(object), False, True - context[objid] = 1 - readable = True - recursive = False - components = [] - append = components.append - level += 1 - items = sorted(object, key=_safe_key) - for item in items: - orepr, oreadable, orecur = self.format( - item, context, maxlevels, level) - append("%s" % orepr) - if not oreadable: - readable = False - if orecur: - recursive = True - del context[objid] - return format % ", ".join(components), readable, recursive - rep = repr(object) return rep, (rep and not rep.startswith('<')), False diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index be1eb932980475..f84ec39109e093 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -486,8 +486,10 @@ def test_set_reprs(self): 5, 6}''') self.assertEqual(pprint.pformat(set2([-1, 0, 1])), "set2({-1, 0, 1})") - self.assertEqual(pprint.pformat(set2("0123")), "set2({'0', '1', '2', '3'})") - self.assertEqual(pprint.pformat(set2("abcd")), "set2({'a', 'b', 'c', 'd'})") + self.assertEqual(pprint.pformat(set2("0123")), + "set2({'0', '1', '2', '3'})") + self.assertEqual(pprint.pformat(set2("abcd")), + "set2({'a', 'b', 'c', 'd'})") self.assertEqual(pprint.pformat(set2(range(7)), width=20), '''\ set2({0, 1,