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