17db96d56Sopenharmony_ci# tests for slice objects; in particular the indices method. 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciimport itertools 47db96d56Sopenharmony_ciimport operator 57db96d56Sopenharmony_ciimport sys 67db96d56Sopenharmony_ciimport unittest 77db96d56Sopenharmony_ciimport weakref 87db96d56Sopenharmony_ciimport copy 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_cifrom pickle import loads, dumps 117db96d56Sopenharmony_cifrom test import support 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_cidef evaluate_slice_index(arg): 157db96d56Sopenharmony_ci """ 167db96d56Sopenharmony_ci Helper function to convert a slice argument to an integer, and raise 177db96d56Sopenharmony_ci TypeError with a suitable message on failure. 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ci """ 207db96d56Sopenharmony_ci if hasattr(arg, '__index__'): 217db96d56Sopenharmony_ci return operator.index(arg) 227db96d56Sopenharmony_ci else: 237db96d56Sopenharmony_ci raise TypeError( 247db96d56Sopenharmony_ci "slice indices must be integers or " 257db96d56Sopenharmony_ci "None or have an __index__ method") 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_cidef slice_indices(slice, length): 287db96d56Sopenharmony_ci """ 297db96d56Sopenharmony_ci Reference implementation for the slice.indices method. 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci """ 327db96d56Sopenharmony_ci # Compute step and length as integers. 337db96d56Sopenharmony_ci length = operator.index(length) 347db96d56Sopenharmony_ci step = 1 if slice.step is None else evaluate_slice_index(slice.step) 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci # Raise ValueError for negative length or zero step. 377db96d56Sopenharmony_ci if length < 0: 387db96d56Sopenharmony_ci raise ValueError("length should not be negative") 397db96d56Sopenharmony_ci if step == 0: 407db96d56Sopenharmony_ci raise ValueError("slice step cannot be zero") 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ci # Find lower and upper bounds for start and stop. 437db96d56Sopenharmony_ci lower = -1 if step < 0 else 0 447db96d56Sopenharmony_ci upper = length - 1 if step < 0 else length 457db96d56Sopenharmony_ci 467db96d56Sopenharmony_ci # Compute start. 477db96d56Sopenharmony_ci if slice.start is None: 487db96d56Sopenharmony_ci start = upper if step < 0 else lower 497db96d56Sopenharmony_ci else: 507db96d56Sopenharmony_ci start = evaluate_slice_index(slice.start) 517db96d56Sopenharmony_ci start = max(start + length, lower) if start < 0 else min(start, upper) 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci # Compute stop. 547db96d56Sopenharmony_ci if slice.stop is None: 557db96d56Sopenharmony_ci stop = lower if step < 0 else upper 567db96d56Sopenharmony_ci else: 577db96d56Sopenharmony_ci stop = evaluate_slice_index(slice.stop) 587db96d56Sopenharmony_ci stop = max(stop + length, lower) if stop < 0 else min(stop, upper) 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci return start, stop, step 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_ci 637db96d56Sopenharmony_ci# Class providing an __index__ method. Used for testing slice.indices. 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ciclass MyIndexable(object): 667db96d56Sopenharmony_ci def __init__(self, value): 677db96d56Sopenharmony_ci self.value = value 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci def __index__(self): 707db96d56Sopenharmony_ci return self.value 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ciclass SliceTest(unittest.TestCase): 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ci def test_constructor(self): 767db96d56Sopenharmony_ci self.assertRaises(TypeError, slice) 777db96d56Sopenharmony_ci self.assertRaises(TypeError, slice, 1, 2, 3, 4) 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_ci def test_repr(self): 807db96d56Sopenharmony_ci self.assertEqual(repr(slice(1, 2, 3)), "slice(1, 2, 3)") 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_ci def test_hash(self): 837db96d56Sopenharmony_ci # Verify clearing of SF bug #800796 847db96d56Sopenharmony_ci self.assertRaises(TypeError, hash, slice(5)) 857db96d56Sopenharmony_ci with self.assertRaises(TypeError): 867db96d56Sopenharmony_ci slice(5).__hash__() 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_ci def test_cmp(self): 897db96d56Sopenharmony_ci s1 = slice(1, 2, 3) 907db96d56Sopenharmony_ci s2 = slice(1, 2, 3) 917db96d56Sopenharmony_ci s3 = slice(1, 2, 4) 927db96d56Sopenharmony_ci self.assertEqual(s1, s2) 937db96d56Sopenharmony_ci self.assertNotEqual(s1, s3) 947db96d56Sopenharmony_ci self.assertNotEqual(s1, None) 957db96d56Sopenharmony_ci self.assertNotEqual(s1, (1, 2, 3)) 967db96d56Sopenharmony_ci self.assertNotEqual(s1, "") 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci class Exc(Exception): 997db96d56Sopenharmony_ci pass 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci class BadCmp(object): 1027db96d56Sopenharmony_ci def __eq__(self, other): 1037db96d56Sopenharmony_ci raise Exc 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci s1 = slice(BadCmp()) 1067db96d56Sopenharmony_ci s2 = slice(BadCmp()) 1077db96d56Sopenharmony_ci self.assertEqual(s1, s1) 1087db96d56Sopenharmony_ci self.assertRaises(Exc, lambda: s1 == s2) 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci s1 = slice(1, BadCmp()) 1117db96d56Sopenharmony_ci s2 = slice(1, BadCmp()) 1127db96d56Sopenharmony_ci self.assertEqual(s1, s1) 1137db96d56Sopenharmony_ci self.assertRaises(Exc, lambda: s1 == s2) 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci s1 = slice(1, 2, BadCmp()) 1167db96d56Sopenharmony_ci s2 = slice(1, 2, BadCmp()) 1177db96d56Sopenharmony_ci self.assertEqual(s1, s1) 1187db96d56Sopenharmony_ci self.assertRaises(Exc, lambda: s1 == s2) 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_ci def test_members(self): 1217db96d56Sopenharmony_ci s = slice(1) 1227db96d56Sopenharmony_ci self.assertEqual(s.start, None) 1237db96d56Sopenharmony_ci self.assertEqual(s.stop, 1) 1247db96d56Sopenharmony_ci self.assertEqual(s.step, None) 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_ci s = slice(1, 2) 1277db96d56Sopenharmony_ci self.assertEqual(s.start, 1) 1287db96d56Sopenharmony_ci self.assertEqual(s.stop, 2) 1297db96d56Sopenharmony_ci self.assertEqual(s.step, None) 1307db96d56Sopenharmony_ci 1317db96d56Sopenharmony_ci s = slice(1, 2, 3) 1327db96d56Sopenharmony_ci self.assertEqual(s.start, 1) 1337db96d56Sopenharmony_ci self.assertEqual(s.stop, 2) 1347db96d56Sopenharmony_ci self.assertEqual(s.step, 3) 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_ci class AnyClass: 1377db96d56Sopenharmony_ci pass 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci obj = AnyClass() 1407db96d56Sopenharmony_ci s = slice(obj) 1417db96d56Sopenharmony_ci self.assertTrue(s.stop is obj) 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ci def check_indices(self, slice, length): 1447db96d56Sopenharmony_ci try: 1457db96d56Sopenharmony_ci actual = slice.indices(length) 1467db96d56Sopenharmony_ci except ValueError: 1477db96d56Sopenharmony_ci actual = "valueerror" 1487db96d56Sopenharmony_ci try: 1497db96d56Sopenharmony_ci expected = slice_indices(slice, length) 1507db96d56Sopenharmony_ci except ValueError: 1517db96d56Sopenharmony_ci expected = "valueerror" 1527db96d56Sopenharmony_ci self.assertEqual(actual, expected) 1537db96d56Sopenharmony_ci 1547db96d56Sopenharmony_ci if length >= 0 and slice.step != 0: 1557db96d56Sopenharmony_ci actual = range(*slice.indices(length)) 1567db96d56Sopenharmony_ci expected = range(length)[slice] 1577db96d56Sopenharmony_ci self.assertEqual(actual, expected) 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci def test_indices(self): 1607db96d56Sopenharmony_ci self.assertEqual(slice(None ).indices(10), (0, 10, 1)) 1617db96d56Sopenharmony_ci self.assertEqual(slice(None, None, 2).indices(10), (0, 10, 2)) 1627db96d56Sopenharmony_ci self.assertEqual(slice(1, None, 2).indices(10), (1, 10, 2)) 1637db96d56Sopenharmony_ci self.assertEqual(slice(None, None, -1).indices(10), (9, -1, -1)) 1647db96d56Sopenharmony_ci self.assertEqual(slice(None, None, -2).indices(10), (9, -1, -2)) 1657db96d56Sopenharmony_ci self.assertEqual(slice(3, None, -2).indices(10), (3, -1, -2)) 1667db96d56Sopenharmony_ci # issue 3004 tests 1677db96d56Sopenharmony_ci self.assertEqual(slice(None, -9).indices(10), (0, 1, 1)) 1687db96d56Sopenharmony_ci self.assertEqual(slice(None, -10).indices(10), (0, 0, 1)) 1697db96d56Sopenharmony_ci self.assertEqual(slice(None, -11).indices(10), (0, 0, 1)) 1707db96d56Sopenharmony_ci self.assertEqual(slice(None, -10, -1).indices(10), (9, 0, -1)) 1717db96d56Sopenharmony_ci self.assertEqual(slice(None, -11, -1).indices(10), (9, -1, -1)) 1727db96d56Sopenharmony_ci self.assertEqual(slice(None, -12, -1).indices(10), (9, -1, -1)) 1737db96d56Sopenharmony_ci self.assertEqual(slice(None, 9).indices(10), (0, 9, 1)) 1747db96d56Sopenharmony_ci self.assertEqual(slice(None, 10).indices(10), (0, 10, 1)) 1757db96d56Sopenharmony_ci self.assertEqual(slice(None, 11).indices(10), (0, 10, 1)) 1767db96d56Sopenharmony_ci self.assertEqual(slice(None, 8, -1).indices(10), (9, 8, -1)) 1777db96d56Sopenharmony_ci self.assertEqual(slice(None, 9, -1).indices(10), (9, 9, -1)) 1787db96d56Sopenharmony_ci self.assertEqual(slice(None, 10, -1).indices(10), (9, 9, -1)) 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci self.assertEqual( 1817db96d56Sopenharmony_ci slice(-100, 100 ).indices(10), 1827db96d56Sopenharmony_ci slice(None).indices(10) 1837db96d56Sopenharmony_ci ) 1847db96d56Sopenharmony_ci self.assertEqual( 1857db96d56Sopenharmony_ci slice(100, -100, -1).indices(10), 1867db96d56Sopenharmony_ci slice(None, None, -1).indices(10) 1877db96d56Sopenharmony_ci ) 1887db96d56Sopenharmony_ci self.assertEqual(slice(-100, 100, 2).indices(10), (0, 10, 2)) 1897db96d56Sopenharmony_ci 1907db96d56Sopenharmony_ci self.assertEqual(list(range(10))[::sys.maxsize - 1], [0]) 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_ci # Check a variety of start, stop, step and length values, including 1937db96d56Sopenharmony_ci # values exceeding sys.maxsize (see issue #14794). 1947db96d56Sopenharmony_ci vals = [None, -2**100, -2**30, -53, -7, -1, 0, 1, 7, 53, 2**30, 2**100] 1957db96d56Sopenharmony_ci lengths = [0, 1, 7, 53, 2**30, 2**100] 1967db96d56Sopenharmony_ci for slice_args in itertools.product(vals, repeat=3): 1977db96d56Sopenharmony_ci s = slice(*slice_args) 1987db96d56Sopenharmony_ci for length in lengths: 1997db96d56Sopenharmony_ci self.check_indices(s, length) 2007db96d56Sopenharmony_ci self.check_indices(slice(0, 10, 1), -3) 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci # Negative length should raise ValueError 2037db96d56Sopenharmony_ci with self.assertRaises(ValueError): 2047db96d56Sopenharmony_ci slice(None).indices(-1) 2057db96d56Sopenharmony_ci 2067db96d56Sopenharmony_ci # Zero step should raise ValueError 2077db96d56Sopenharmony_ci with self.assertRaises(ValueError): 2087db96d56Sopenharmony_ci slice(0, 10, 0).indices(5) 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_ci # Using a start, stop or step or length that can't be interpreted as an 2117db96d56Sopenharmony_ci # integer should give a TypeError ... 2127db96d56Sopenharmony_ci with self.assertRaises(TypeError): 2137db96d56Sopenharmony_ci slice(0.0, 10, 1).indices(5) 2147db96d56Sopenharmony_ci with self.assertRaises(TypeError): 2157db96d56Sopenharmony_ci slice(0, 10.0, 1).indices(5) 2167db96d56Sopenharmony_ci with self.assertRaises(TypeError): 2177db96d56Sopenharmony_ci slice(0, 10, 1.0).indices(5) 2187db96d56Sopenharmony_ci with self.assertRaises(TypeError): 2197db96d56Sopenharmony_ci slice(0, 10, 1).indices(5.0) 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_ci # ... but it should be fine to use a custom class that provides index. 2227db96d56Sopenharmony_ci self.assertEqual(slice(0, 10, 1).indices(5), (0, 5, 1)) 2237db96d56Sopenharmony_ci self.assertEqual(slice(MyIndexable(0), 10, 1).indices(5), (0, 5, 1)) 2247db96d56Sopenharmony_ci self.assertEqual(slice(0, MyIndexable(10), 1).indices(5), (0, 5, 1)) 2257db96d56Sopenharmony_ci self.assertEqual(slice(0, 10, MyIndexable(1)).indices(5), (0, 5, 1)) 2267db96d56Sopenharmony_ci self.assertEqual(slice(0, 10, 1).indices(MyIndexable(5)), (0, 5, 1)) 2277db96d56Sopenharmony_ci 2287db96d56Sopenharmony_ci def test_setslice_without_getslice(self): 2297db96d56Sopenharmony_ci tmp = [] 2307db96d56Sopenharmony_ci class X(object): 2317db96d56Sopenharmony_ci def __setitem__(self, i, k): 2327db96d56Sopenharmony_ci tmp.append((i, k)) 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ci x = X() 2357db96d56Sopenharmony_ci x[1:2] = 42 2367db96d56Sopenharmony_ci self.assertEqual(tmp, [(slice(1, 2), 42)]) 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ci def test_pickle(self): 2397db96d56Sopenharmony_ci import pickle 2407db96d56Sopenharmony_ci 2417db96d56Sopenharmony_ci s = slice(10, 20, 3) 2427db96d56Sopenharmony_ci for protocol in range(pickle.HIGHEST_PROTOCOL + 1): 2437db96d56Sopenharmony_ci t = loads(dumps(s, protocol)) 2447db96d56Sopenharmony_ci self.assertEqual(s, t) 2457db96d56Sopenharmony_ci self.assertEqual(s.indices(15), t.indices(15)) 2467db96d56Sopenharmony_ci self.assertNotEqual(id(s), id(t)) 2477db96d56Sopenharmony_ci 2487db96d56Sopenharmony_ci def test_copy(self): 2497db96d56Sopenharmony_ci s = slice(1, 10) 2507db96d56Sopenharmony_ci c = copy.copy(s) 2517db96d56Sopenharmony_ci self.assertIs(s, c) 2527db96d56Sopenharmony_ci 2537db96d56Sopenharmony_ci s = slice(1, 10, 2) 2547db96d56Sopenharmony_ci c = copy.copy(s) 2557db96d56Sopenharmony_ci self.assertIs(s, c) 2567db96d56Sopenharmony_ci 2577db96d56Sopenharmony_ci # Corner case for mutable indices: 2587db96d56Sopenharmony_ci s = slice([1, 2], [3, 4], [5, 6]) 2597db96d56Sopenharmony_ci c = copy.copy(s) 2607db96d56Sopenharmony_ci self.assertIs(s, c) 2617db96d56Sopenharmony_ci self.assertIs(s.start, c.start) 2627db96d56Sopenharmony_ci self.assertIs(s.stop, c.stop) 2637db96d56Sopenharmony_ci self.assertIs(s.step, c.step) 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_ci def test_deepcopy(self): 2667db96d56Sopenharmony_ci s = slice(1, 10) 2677db96d56Sopenharmony_ci c = copy.deepcopy(s) 2687db96d56Sopenharmony_ci self.assertEqual(s, c) 2697db96d56Sopenharmony_ci 2707db96d56Sopenharmony_ci s = slice(1, 10, 2) 2717db96d56Sopenharmony_ci c = copy.deepcopy(s) 2727db96d56Sopenharmony_ci self.assertEqual(s, c) 2737db96d56Sopenharmony_ci 2747db96d56Sopenharmony_ci # Corner case for mutable indices: 2757db96d56Sopenharmony_ci s = slice([1, 2], [3, 4], [5, 6]) 2767db96d56Sopenharmony_ci c = copy.deepcopy(s) 2777db96d56Sopenharmony_ci self.assertIsNot(s, c) 2787db96d56Sopenharmony_ci self.assertEqual(s, c) 2797db96d56Sopenharmony_ci self.assertIsNot(s.start, c.start) 2807db96d56Sopenharmony_ci self.assertIsNot(s.stop, c.stop) 2817db96d56Sopenharmony_ci self.assertIsNot(s.step, c.step) 2827db96d56Sopenharmony_ci 2837db96d56Sopenharmony_ci def test_cycle(self): 2847db96d56Sopenharmony_ci class myobj(): pass 2857db96d56Sopenharmony_ci o = myobj() 2867db96d56Sopenharmony_ci o.s = slice(o) 2877db96d56Sopenharmony_ci w = weakref.ref(o) 2887db96d56Sopenharmony_ci o = None 2897db96d56Sopenharmony_ci support.gc_collect() 2907db96d56Sopenharmony_ci self.assertIsNone(w()) 2917db96d56Sopenharmony_ci 2927db96d56Sopenharmony_ciif __name__ == "__main__": 2937db96d56Sopenharmony_ci unittest.main() 294