17db96d56Sopenharmony_cifrom collections import deque
27db96d56Sopenharmony_ciimport unittest
37db96d56Sopenharmony_cifrom test.support import NEVER_EQ
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ciclass base_set:
77db96d56Sopenharmony_ci    def __init__(self, el):
87db96d56Sopenharmony_ci        self.el = el
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ciclass myset(base_set):
117db96d56Sopenharmony_ci    def __contains__(self, el):
127db96d56Sopenharmony_ci        return self.el == el
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ciclass seq(base_set):
157db96d56Sopenharmony_ci    def __getitem__(self, n):
167db96d56Sopenharmony_ci        return [self.el][n]
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ciclass TestContains(unittest.TestCase):
197db96d56Sopenharmony_ci    def test_common_tests(self):
207db96d56Sopenharmony_ci        a = base_set(1)
217db96d56Sopenharmony_ci        b = myset(1)
227db96d56Sopenharmony_ci        c = seq(1)
237db96d56Sopenharmony_ci        self.assertIn(1, b)
247db96d56Sopenharmony_ci        self.assertNotIn(0, b)
257db96d56Sopenharmony_ci        self.assertIn(1, c)
267db96d56Sopenharmony_ci        self.assertNotIn(0, c)
277db96d56Sopenharmony_ci        self.assertRaises(TypeError, lambda: 1 in a)
287db96d56Sopenharmony_ci        self.assertRaises(TypeError, lambda: 1 not in a)
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci        # test char in string
317db96d56Sopenharmony_ci        self.assertIn('c', 'abc')
327db96d56Sopenharmony_ci        self.assertNotIn('d', 'abc')
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ci        self.assertIn('', '')
357db96d56Sopenharmony_ci        self.assertIn('', 'abc')
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci        self.assertRaises(TypeError, lambda: None in 'abc')
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci    def test_builtin_sequence_types(self):
407db96d56Sopenharmony_ci        # a collection of tests on builtin sequence types
417db96d56Sopenharmony_ci        a = range(10)
427db96d56Sopenharmony_ci        for i in a:
437db96d56Sopenharmony_ci            self.assertIn(i, a)
447db96d56Sopenharmony_ci        self.assertNotIn(16, a)
457db96d56Sopenharmony_ci        self.assertNotIn(a, a)
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci        a = tuple(a)
487db96d56Sopenharmony_ci        for i in a:
497db96d56Sopenharmony_ci            self.assertIn(i, a)
507db96d56Sopenharmony_ci        self.assertNotIn(16, a)
517db96d56Sopenharmony_ci        self.assertNotIn(a, a)
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ci        class Deviant1:
547db96d56Sopenharmony_ci            """Behaves strangely when compared
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci            This class is designed to make sure that the contains code
577db96d56Sopenharmony_ci            works when the list is modified during the check.
587db96d56Sopenharmony_ci            """
597db96d56Sopenharmony_ci            aList = list(range(15))
607db96d56Sopenharmony_ci            def __eq__(self, other):
617db96d56Sopenharmony_ci                if other == 12:
627db96d56Sopenharmony_ci                    self.aList.remove(12)
637db96d56Sopenharmony_ci                    self.aList.remove(13)
647db96d56Sopenharmony_ci                    self.aList.remove(14)
657db96d56Sopenharmony_ci                return 0
667db96d56Sopenharmony_ci
677db96d56Sopenharmony_ci        self.assertNotIn(Deviant1(), Deviant1.aList)
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ci    def test_nonreflexive(self):
707db96d56Sopenharmony_ci        # containment and equality tests involving elements that are
717db96d56Sopenharmony_ci        # not necessarily equal to themselves
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ci        values = float('nan'), 1, None, 'abc', NEVER_EQ
747db96d56Sopenharmony_ci        constructors = list, tuple, dict.fromkeys, set, frozenset, deque
757db96d56Sopenharmony_ci        for constructor in constructors:
767db96d56Sopenharmony_ci            container = constructor(values)
777db96d56Sopenharmony_ci            for elem in container:
787db96d56Sopenharmony_ci                self.assertIn(elem, container)
797db96d56Sopenharmony_ci            self.assertTrue(container == constructor(values))
807db96d56Sopenharmony_ci            self.assertTrue(container == container)
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_ci    def test_block_fallback(self):
837db96d56Sopenharmony_ci        # blocking fallback with __contains__ = None
847db96d56Sopenharmony_ci        class ByContains(object):
857db96d56Sopenharmony_ci            def __contains__(self, other):
867db96d56Sopenharmony_ci                return False
877db96d56Sopenharmony_ci        c = ByContains()
887db96d56Sopenharmony_ci        class BlockContains(ByContains):
897db96d56Sopenharmony_ci            """Is not a container
907db96d56Sopenharmony_ci
917db96d56Sopenharmony_ci            This class is a perfectly good iterable (as tested by
927db96d56Sopenharmony_ci            list(bc)), as well as inheriting from a perfectly good
937db96d56Sopenharmony_ci            container, but __contains__ = None prevents the usual
947db96d56Sopenharmony_ci            fallback to iteration in the container protocol. That
957db96d56Sopenharmony_ci            is, normally, 0 in bc would fall back to the equivalent
967db96d56Sopenharmony_ci            of any(x==0 for x in bc), but here it's blocked from
977db96d56Sopenharmony_ci            doing so.
987db96d56Sopenharmony_ci            """
997db96d56Sopenharmony_ci            def __iter__(self):
1007db96d56Sopenharmony_ci                while False:
1017db96d56Sopenharmony_ci                    yield None
1027db96d56Sopenharmony_ci            __contains__ = None
1037db96d56Sopenharmony_ci        bc = BlockContains()
1047db96d56Sopenharmony_ci        self.assertFalse(0 in c)
1057db96d56Sopenharmony_ci        self.assertFalse(0 in list(bc))
1067db96d56Sopenharmony_ci        self.assertRaises(TypeError, lambda: 0 in bc)
1077db96d56Sopenharmony_ci
1087db96d56Sopenharmony_ciif __name__ == '__main__':
1097db96d56Sopenharmony_ci    unittest.main()
110