Skip to content

Commit 7ac49e7

Browse files
authored
gh-111147: Fix test_set_of_sets_reprs in test_pprint (GH-111148)
Make it stable and not depending on implementation details.
1 parent fb79e1e commit 7ac49e7

File tree

1 file changed

+95
-197
lines changed

1 file changed

+95
-197
lines changed

Lib/test/test_pprint.py

Lines changed: 95 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import random
1010
import re
1111
import test.support
12-
import test.test_set
1312
import types
1413
import unittest
1514

@@ -623,9 +622,6 @@ def test_set_reprs(self):
623622
self.assertEqual(pprint.pformat(frozenset3(range(7)), width=20),
624623
'frozenset3({0, 1, 2, 3, 4, 5, 6})')
625624

626-
@unittest.expectedFailure
627-
#See http://bugs.python.org/issue13907
628-
@test.support.cpython_only
629625
def test_set_of_sets_reprs(self):
630626
# This test creates a complex arrangement of frozensets and
631627
# compares the pretty-printed repr against a string hard-coded in
@@ -636,204 +632,106 @@ def test_set_of_sets_reprs(self):
636632
# partial ordering (subset relationships), the output of the
637633
# list.sort() method is undefined for lists of sets."
638634
#
639-
# In a nutshell, the test assumes frozenset({0}) will always
640-
# sort before frozenset({1}), but:
641-
#
642635
# >>> frozenset({0}) < frozenset({1})
643636
# False
644637
# >>> frozenset({1}) < frozenset({0})
645638
# False
646639
#
647-
# Consequently, this test is fragile and
648-
# implementation-dependent. Small changes to Python's sort
649-
# algorithm cause the test to fail when it should pass.
650-
# XXX Or changes to the dictionary implementation...
651-
652-
cube_repr_tgt = """\
653-
{frozenset(): frozenset({frozenset({2}), frozenset({0}), frozenset({1})}),
654-
frozenset({0}): frozenset({frozenset(),
655-
frozenset({0, 2}),
656-
frozenset({0, 1})}),
657-
frozenset({1}): frozenset({frozenset(),
658-
frozenset({1, 2}),
659-
frozenset({0, 1})}),
660-
frozenset({2}): frozenset({frozenset(),
661-
frozenset({1, 2}),
662-
frozenset({0, 2})}),
663-
frozenset({1, 2}): frozenset({frozenset({2}),
664-
frozenset({1}),
665-
frozenset({0, 1, 2})}),
666-
frozenset({0, 2}): frozenset({frozenset({2}),
667-
frozenset({0}),
668-
frozenset({0, 1, 2})}),
669-
frozenset({0, 1}): frozenset({frozenset({0}),
670-
frozenset({1}),
671-
frozenset({0, 1, 2})}),
672-
frozenset({0, 1, 2}): frozenset({frozenset({1, 2}),
673-
frozenset({0, 2}),
674-
frozenset({0, 1})})}"""
675-
cube = test.test_set.cube(3)
676-
self.assertEqual(pprint.pformat(cube), cube_repr_tgt)
677-
cubo_repr_tgt = """\
678-
{frozenset({frozenset({0, 2}), frozenset({0})}): frozenset({frozenset({frozenset({0,
679-
2}),
680-
frozenset({0,
681-
1,
682-
2})}),
683-
frozenset({frozenset({0}),
684-
frozenset({0,
685-
1})}),
686-
frozenset({frozenset(),
687-
frozenset({0})}),
688-
frozenset({frozenset({2}),
689-
frozenset({0,
690-
2})})}),
691-
frozenset({frozenset({0, 1}), frozenset({1})}): frozenset({frozenset({frozenset({0,
692-
1}),
693-
frozenset({0,
694-
1,
695-
2})}),
696-
frozenset({frozenset({0}),
697-
frozenset({0,
698-
1})}),
699-
frozenset({frozenset({1}),
700-
frozenset({1,
701-
2})}),
702-
frozenset({frozenset(),
703-
frozenset({1})})}),
704-
frozenset({frozenset({1, 2}), frozenset({1})}): frozenset({frozenset({frozenset({1,
705-
2}),
706-
frozenset({0,
707-
1,
708-
2})}),
709-
frozenset({frozenset({2}),
710-
frozenset({1,
711-
2})}),
712-
frozenset({frozenset(),
713-
frozenset({1})}),
714-
frozenset({frozenset({1}),
715-
frozenset({0,
716-
1})})}),
717-
frozenset({frozenset({1, 2}), frozenset({2})}): frozenset({frozenset({frozenset({1,
718-
2}),
719-
frozenset({0,
720-
1,
721-
2})}),
722-
frozenset({frozenset({1}),
723-
frozenset({1,
724-
2})}),
725-
frozenset({frozenset({2}),
726-
frozenset({0,
727-
2})}),
728-
frozenset({frozenset(),
729-
frozenset({2})})}),
730-
frozenset({frozenset(), frozenset({0})}): frozenset({frozenset({frozenset({0}),
731-
frozenset({0,
732-
1})}),
733-
frozenset({frozenset({0}),
734-
frozenset({0,
735-
2})}),
736-
frozenset({frozenset(),
737-
frozenset({1})}),
738-
frozenset({frozenset(),
739-
frozenset({2})})}),
740-
frozenset({frozenset(), frozenset({1})}): frozenset({frozenset({frozenset(),
741-
frozenset({0})}),
742-
frozenset({frozenset({1}),
743-
frozenset({1,
744-
2})}),
745-
frozenset({frozenset(),
746-
frozenset({2})}),
747-
frozenset({frozenset({1}),
748-
frozenset({0,
749-
1})})}),
750-
frozenset({frozenset({2}), frozenset()}): frozenset({frozenset({frozenset({2}),
751-
frozenset({1,
752-
2})}),
753-
frozenset({frozenset(),
754-
frozenset({0})}),
755-
frozenset({frozenset(),
756-
frozenset({1})}),
757-
frozenset({frozenset({2}),
758-
frozenset({0,
759-
2})})}),
760-
frozenset({frozenset({0, 1, 2}), frozenset({0, 1})}): frozenset({frozenset({frozenset({1,
761-
2}),
762-
frozenset({0,
763-
1,
764-
2})}),
765-
frozenset({frozenset({0,
766-
2}),
767-
frozenset({0,
768-
1,
769-
2})}),
770-
frozenset({frozenset({0}),
771-
frozenset({0,
772-
1})}),
773-
frozenset({frozenset({1}),
774-
frozenset({0,
775-
1})})}),
776-
frozenset({frozenset({0}), frozenset({0, 1})}): frozenset({frozenset({frozenset(),
777-
frozenset({0})}),
778-
frozenset({frozenset({0,
779-
1}),
780-
frozenset({0,
781-
1,
782-
2})}),
783-
frozenset({frozenset({0}),
784-
frozenset({0,
785-
2})}),
786-
frozenset({frozenset({1}),
787-
frozenset({0,
788-
1})})}),
789-
frozenset({frozenset({2}), frozenset({0, 2})}): frozenset({frozenset({frozenset({0,
790-
2}),
791-
frozenset({0,
792-
1,
793-
2})}),
794-
frozenset({frozenset({2}),
795-
frozenset({1,
796-
2})}),
797-
frozenset({frozenset({0}),
798-
frozenset({0,
799-
2})}),
800-
frozenset({frozenset(),
801-
frozenset({2})})}),
802-
frozenset({frozenset({0, 1, 2}), frozenset({0, 2})}): frozenset({frozenset({frozenset({1,
803-
2}),
804-
frozenset({0,
805-
1,
806-
2})}),
807-
frozenset({frozenset({0,
808-
1}),
809-
frozenset({0,
810-
1,
811-
2})}),
812-
frozenset({frozenset({0}),
813-
frozenset({0,
814-
2})}),
815-
frozenset({frozenset({2}),
816-
frozenset({0,
817-
2})})}),
818-
frozenset({frozenset({1, 2}), frozenset({0, 1, 2})}): frozenset({frozenset({frozenset({0,
819-
2}),
820-
frozenset({0,
821-
1,
822-
2})}),
823-
frozenset({frozenset({0,
824-
1}),
825-
frozenset({0,
826-
1,
827-
2})}),
828-
frozenset({frozenset({2}),
829-
frozenset({1,
830-
2})}),
831-
frozenset({frozenset({1}),
832-
frozenset({1,
833-
2})})})}"""
834-
835-
cubo = test.test_set.linegraph(cube)
836-
self.assertEqual(pprint.pformat(cubo), cubo_repr_tgt)
640+
# In this test we list all possible invariants of the result
641+
# for unordered frozensets.
642+
#
643+
# This test has a long history, see:
644+
# - https://github.com/python/cpython/commit/969fe57baa0eb80332990f9cda936a33e13fabef
645+
# - https://github.com/python/cpython/issues/58115
646+
# - https://github.com/python/cpython/issues/111147
647+
648+
import textwrap
649+
650+
# Single-line, always ordered:
651+
fs0 = frozenset()
652+
fs1 = frozenset(('abc', 'xyz'))
653+
data = frozenset((fs0, fs1))
654+
self.assertEqual(pprint.pformat(data),
655+
'frozenset({%r, %r})' % (fs0, fs1))
656+
self.assertEqual(pprint.pformat(data), repr(data))
657+
658+
fs2 = frozenset(('one', 'two'))
659+
data = {fs2: frozenset((fs0, fs1))}
660+
self.assertEqual(pprint.pformat(data),
661+
"{%r: frozenset({%r, %r})}" % (fs2, fs0, fs1))
662+
self.assertEqual(pprint.pformat(data), repr(data))
663+
664+
# Single-line, unordered:
665+
fs1 = frozenset(("xyz", "qwerty"))
666+
fs2 = frozenset(("abcd", "spam"))
667+
fs = frozenset((fs1, fs2))
668+
self.assertEqual(pprint.pformat(fs), repr(fs))
669+
670+
# Multiline, unordered:
671+
def check(res, invariants):
672+
self.assertIn(res, [textwrap.dedent(i).strip() for i in invariants])
673+
674+
# Inner-most frozensets are singleline, result is multiline, unordered:
675+
fs1 = frozenset(('regular string', 'other string'))
676+
fs2 = frozenset(('third string', 'one more string'))
677+
check(
678+
pprint.pformat(frozenset((fs1, fs2))),
679+
[
680+
"""
681+
frozenset({%r,
682+
%r})
683+
""" % (fs1, fs2),
684+
"""
685+
frozenset({%r,
686+
%r})
687+
""" % (fs2, fs1),
688+
],
689+
)
690+
691+
# Everything is multiline, unordered:
692+
check(
693+
pprint.pformat(
694+
frozenset((
695+
frozenset((
696+
"xyz very-very long string",
697+
"qwerty is also absurdly long",
698+
)),
699+
frozenset((
700+
"abcd is even longer that before",
701+
"spam is not so long",
702+
)),
703+
)),
704+
),
705+
[
706+
"""
707+
frozenset({frozenset({'abcd is even longer that before',
708+
'spam is not so long'}),
709+
frozenset({'qwerty is also absurdly long',
710+
'xyz very-very long string'})})
711+
""",
712+
713+
"""
714+
frozenset({frozenset({'abcd is even longer that before',
715+
'spam is not so long'}),
716+
frozenset({'xyz very-very long string',
717+
'qwerty is also absurdly long'})})
718+
""",
719+
720+
"""
721+
frozenset({frozenset({'qwerty is also absurdly long',
722+
'xyz very-very long string'}),
723+
frozenset({'abcd is even longer that before',
724+
'spam is not so long'})})
725+
""",
726+
727+
"""
728+
frozenset({frozenset({'qwerty is also absurdly long',
729+
'xyz very-very long string'}),
730+
frozenset({'spam is not so long',
731+
'abcd is even longer that before'})})
732+
""",
733+
],
734+
)
837735

838736
def test_depth(self):
839737
nested_tuple = (1, (2, (3, (4, (5, 6)))))

0 commit comments

Comments
 (0)