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