Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(6)

## Side by Side Diff: Lib/test/test_slice.py

Issue 14794: slice.indices raises OverflowError
Patch Set: Created 7 years, 4 months ago
 Left: Base Patch Set 1: None Patch Set 2: None Patch Set 3: None Patch Set 4: None Right: Patch Set 1: None Patch Set 2: None Patch Set 3: None Patch Set 4: None
« no previous file with comments | « no previous file | Objects/sliceobject.c » ('j') | Objects/sliceobject.c » ('J')
OLDNEW
1 # tests for slice objects; in particular the indices method. 1 # tests for slice objects; in particular the indices method.
2 2
3 import unittest 3 import unittest
4 from test import support 4 from test import support
5 from pickle import loads, dumps 5 from pickle import loads, dumps
6 6
7 import operator
7 import sys 8 import sys
9
10
11 def slice_indices(slice, length):
storchaka 2012/11/03 21:56:32 Can we use Python implementation for builtin objec
mark.dickinson 2012/11/03 23:14:48 I don't understand what you mean. Can you elabora
12 """
13 Python reference implementation of the slice.indices method.
14
15 """
16 # Compute step and length as integers.
17 step = 1 if slice.step is None else operator.index(slice.step)
18 length = operator.index(length)
19
20 # Check error conditions.
21 if step == 0:
22 raise ValueError("slice step cannot be zero")
23 if length < 0:
24 raise ValueError("length should be nonnegative")
25
26 # Get lower and upper bounds for start and stop.
27 lower = -1 if step < 0 else 0
28 upper = length - 1 if step < 0 else length
29
30 # Compute start.
31 if slice.start is None:
32 start = upper if step < 0 else lower
33 else:
34 start = operator.index(slice.start)
35 start = max(start + length, lower) if start < 0 else min(start, upper)
36
37 # Compute stop.
38 if slice.stop is None:
39 stop = lower if step < 0 else upper
40 else:
41 stop = operator.index(slice.stop)
42 stop = max(stop + length, lower) if stop < 0 else min(stop, upper)
43
44 return start, stop, step
45
46
47 # Class providing an __index__ method. Used in testing.
48
49 class MyIndexable(object):
50 def __init__(self, value):
51 self.value = value
52
53 def __index__(self):
54 return self.value
55
8 56
9 class SliceTest(unittest.TestCase): 57 class SliceTest(unittest.TestCase):
10 58
11 def test_constructor(self): 59 def test_constructor(self):
12 self.assertRaises(TypeError, slice) 60 self.assertRaises(TypeError, slice)
13 self.assertRaises(TypeError, slice, 1, 2, 3, 4) 61 self.assertRaises(TypeError, slice, 1, 2, 3, 4)
14 62
15 def test_repr(self): 63 def test_repr(self):
16 self.assertEqual(repr(slice(1, 2, 3)), "slice(1, 2, 3)") 64 self.assertEqual(repr(slice(1, 2, 3)), "slice(1, 2, 3)")
17 65
(...skipping 49 matching lines...)
67 self.assertEqual(s.start, 1) 115 self.assertEqual(s.start, 1)
68 self.assertEqual(s.stop, 2) 116 self.assertEqual(s.stop, 2)
69 self.assertEqual(s.step, 3) 117 self.assertEqual(s.step, 3)
70 118
71 class AnyClass: 119 class AnyClass:
72 pass 120 pass
73 121
74 obj = AnyClass() 122 obj = AnyClass()
75 s = slice(obj) 123 s = slice(obj)
76 self.assertTrue(s.stop is obj) 124 self.assertTrue(s.stop is obj)
125
126 def check_indices(self, slice, length):
127 try:
128 expected = slice.indices(length)
129 except ValueError:
130 expected = "valueerror"
131 try:
132 actual = slice_indices(slice, length)
133 except ValueError:
134 actual = "valueerror"
135
136 self.assertEqual(actual, expected)
137
138 if slice.step == 0:
139 return
140
141 # Check the indices we're getting.
142 self.assertEqual(
143 range(*slice_indices(slice, length)),
144 range(length)[slice],
145 )
77 146
78 def test_indices(self): 147 def test_indices(self):
79 self.assertEqual(slice(None ).indices(10), (0, 10, 1)) 148 self.assertEqual(slice(None ).indices(10), (0, 10, 1))
80 self.assertEqual(slice(None, None, 2).indices(10), (0, 10, 2)) 149 self.assertEqual(slice(None, None, 2).indices(10), (0, 10, 2))
81 self.assertEqual(slice(1, None, 2).indices(10), (1, 10, 2)) 150 self.assertEqual(slice(1, None, 2).indices(10), (1, 10, 2))
82 self.assertEqual(slice(None, None, -1).indices(10), (9, -1, -1)) 151 self.assertEqual(slice(None, None, -1).indices(10), (9, -1, -1))
83 self.assertEqual(slice(None, None, -2).indices(10), (9, -1, -2)) 152 self.assertEqual(slice(None, None, -2).indices(10), (9, -1, -2))
84 self.assertEqual(slice(3, None, -2).indices(10), (3, -1, -2)) 153 self.assertEqual(slice(3, None, -2).indices(10), (3, -1, -2))
85 # issue 3004 tests 154 # issue 3004 tests
86 self.assertEqual(slice(None, -9).indices(10), (0, 1, 1)) 155 self.assertEqual(slice(None, -9).indices(10), (0, 1, 1))
(...skipping 14 matching lines...) Expand all
101 slice(None).indices(10) 170 slice(None).indices(10)
102 ) 171 )
103 self.assertEqual( 172 self.assertEqual(
104 slice(100, -100, -1).indices(10), 173 slice(100, -100, -1).indices(10),
105 slice(None, None, -1).indices(10) 174 slice(None, None, -1).indices(10)
106 ) 175 )
107 self.assertEqual(slice(-100, 100, 2).indices(10), (0, 10, 2)) 176 self.assertEqual(slice(-100, 100, 2).indices(10), (0, 10, 2))
108 177
109 self.assertEqual(list(range(10))[::sys.maxsize - 1], [0]) 178 self.assertEqual(list(range(10))[::sys.maxsize - 1], [0])
110 179
111 self.assertRaises(OverflowError, slice(None).indices, 1<<100) 180 # Check a variety of start, stop, step and length values, including
181 # values exceeding sys.maxsize (see issue #14794).
182 vals = [None, -2**100, -2**30, -53, -7, -1, 0, 1, 7, 53, 2**30, 2**100]
183 lengths = [0, 1, 7, 53, 2**30, 2**100]
184 for start in vals:
185 for stop in vals:
186 for step in vals:
187 s = slice(start, stop, step)
188 for length in lengths:
189 self.check_indices(s, length)
190
191 # Negative length should raise ValueError
192 with self.assertRaises(ValueError):
193 slice(None).indices(-1)
194
195 # Zero step should raise ValueError
196 with self.assertRaises(ValueError):
197 slice(0, 10, 0).indices(5)
198
199 # Using a start, stop or step or length that can't be interpreted as an
200 # integer should give a TypeError ...
201 with self.assertRaises(TypeError):
202 slice(0.0, 10, 1).indices(5)
203 with self.assertRaises(TypeError):
204 slice(0, 10.0, 1).indices(5)
205 with self.assertRaises(TypeError):
206 slice(0, 10, 1.0).indices(5)
207 with self.assertRaises(TypeError):
208 slice(0, 10, 1).indices(5.0)
209
210 # ... but it should be fine to use a custom class that provides index.
211 self.assertEqual(slice(0, 10, 1).indices(5), (0, 5, 1))
212 self.assertEqual(slice(MyIndexable(0), 10, 1).indices(5), (0, 5, 1))
213 self.assertEqual(slice(0, MyIndexable(10), 1).indices(5), (0, 5, 1))
214 self.assertEqual(slice(0, 10, MyIndexable(1)).indices(5), (0, 5, 1))
215 self.assertEqual(slice(0, 10, 1).indices(MyIndexable(5)), (0, 5, 1))
112 216
113 def test_setslice_without_getslice(self): 217 def test_setslice_without_getslice(self):
114 tmp = [] 218 tmp = []
115 class X(object): 219 class X(object):
116 def __setitem__(self, i, k): 220 def __setitem__(self, i, k):
117 tmp.append((i, k)) 221 tmp.append((i, k))
118 222
119 x = X() 223 x = X()
120 x[1:2] = 42 224 x[1:2] = 42
121 self.assertEqual(tmp, [(slice(1, 2), 42)]) 225 self.assertEqual(tmp, [(slice(1, 2), 42)])
122 226
123 def test_pickle(self): 227 def test_pickle(self):
124 s = slice(10, 20, 3) 228 s = slice(10, 20, 3)
125 for protocol in (0,1,2): 229 for protocol in (0,1,2):