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

Delta Between Two Patch Sets: Lib/test/test_slice.py

Issue 14794: slice.indices raises OverflowError
Left Patch Set: Created 6 years, 8 months ago
Right Patch Set: Created 6 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | Objects/sliceobject.c » ('j') | Objects/sliceobject.c » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 itertools
7 import operator 8 import operator
8 import sys 9 import sys
9 10
10 11
12 def evaluate_slice_index(arg):
13 """
14 Helper function to convert a slice argument to an integer, and raise
15 TypeError with a suitable message on failure.
16
17 """
18 if hasattr(arg, '__index__'):
19 return operator.index(arg)
20 else:
21 raise TypeError(
22 "slice indices must be integers or "
23 "None or have an __index__ method")
24
11 def slice_indices(slice, length): 25 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 """ 26 """
13 Python reference implementation of the slice.indices method. 27 Reference implementation for the slice.indices method.
14 28
15 """ 29 """
16 # Compute step and length as integers. 30 # Compute step and length as integers.
17 step = 1 if slice.step is None else operator.index(slice.step)
18 length = operator.index(length) 31 length = operator.index(length)
19 32 step = 1 if slice.step is None else evaluate_slice_index(slice.step)
20 # Check error conditions. 33
34 # Raise ValueError for negative length or zero step.
35 if length < 0:
36 raise ValueError("length should not be negative")
21 if step == 0: 37 if step == 0:
22 raise ValueError("slice step cannot be zero") 38 raise ValueError("slice step cannot be zero")
23 if length < 0: 39
24 raise ValueError("length should be nonnegative") 40 # Find lower and upper bounds for start and stop.
25
26 # Get lower and upper bounds for start and stop.
27 lower = -1 if step < 0 else 0 41 lower = -1 if step < 0 else 0
28 upper = length - 1 if step < 0 else length 42 upper = length - 1 if step < 0 else length
29 43
30 # Compute start. 44 # Compute start.
31 if slice.start is None: 45 if slice.start is None:
32 start = upper if step < 0 else lower 46 start = upper if step < 0 else lower
33 else: 47 else:
34 start = operator.index(slice.start) 48 start = evaluate_slice_index(slice.start)
35 start = max(start + length, lower) if start < 0 else min(start, upper) 49 start = max(start + length, lower) if start < 0 else min(start, upper)
36 50
37 # Compute stop. 51 # Compute stop.
38 if slice.stop is None: 52 if slice.stop is None:
39 stop = lower if step < 0 else upper 53 stop = lower if step < 0 else upper
40 else: 54 else:
41 stop = operator.index(slice.stop) 55 stop = evaluate_slice_index(slice.stop)
42 stop = max(stop + length, lower) if stop < 0 else min(stop, upper) 56 stop = max(stop + length, lower) if stop < 0 else min(stop, upper)
43 57
44 return start, stop, step 58 return start, stop, step
45 59
46 60
47 # Class providing an __index__ method. Used in testing. 61 # Class providing an __index__ method. Used for testing slice.indices.
48 62
49 class MyIndexable(object): 63 class MyIndexable(object):
50 def __init__(self, value): 64 def __init__(self, value):
51 self.value = value 65 self.value = value
52 66
53 def __index__(self): 67 def __index__(self):
54 return self.value 68 return self.value
55 69
56 70
57 class SliceTest(unittest.TestCase): 71 class SliceTest(unittest.TestCase):
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 132
119 class AnyClass: 133 class AnyClass:
120 pass 134 pass
121 135
122 obj = AnyClass() 136 obj = AnyClass()
123 s = slice(obj) 137 s = slice(obj)
124 self.assertTrue(s.stop is obj) 138 self.assertTrue(s.stop is obj)
125 139
126 def check_indices(self, slice, length): 140 def check_indices(self, slice, length):
127 try: 141 try:
128 expected = slice.indices(length) 142 actual = slice.indices(length)
143 except ValueError:
144 actual = "valueerror"
145 try:
146 expected = slice_indices(slice, length)
129 except ValueError: 147 except ValueError:
130 expected = "valueerror" 148 expected = "valueerror"
131 try:
132 actual = slice_indices(slice, length)
133 except ValueError:
134 actual = "valueerror"
135
136 self.assertEqual(actual, expected) 149 self.assertEqual(actual, expected)
137 150
138 if slice.step == 0: 151 if length >= 0 and slice.step != 0:
139 return 152 actual = range(*slice.indices(length))
140 153 expected = range(length)[slice]
141 # Check the indices we're getting. 154 self.assertEqual(actual, expected)
142 self.assertEqual(
143 range(*slice_indices(slice, length)),
144 range(length)[slice],
145 )
146 155
147 def test_indices(self): 156 def test_indices(self):
148 self.assertEqual(slice(None ).indices(10), (0, 10, 1)) 157 self.assertEqual(slice(None ).indices(10), (0, 10, 1))
149 self.assertEqual(slice(None, None, 2).indices(10), (0, 10, 2)) 158 self.assertEqual(slice(None, None, 2).indices(10), (0, 10, 2))
150 self.assertEqual(slice(1, None, 2).indices(10), (1, 10, 2)) 159 self.assertEqual(slice(1, None, 2).indices(10), (1, 10, 2))
151 self.assertEqual(slice(None, None, -1).indices(10), (9, -1, -1)) 160 self.assertEqual(slice(None, None, -1).indices(10), (9, -1, -1))
152 self.assertEqual(slice(None, None, -2).indices(10), (9, -1, -2)) 161 self.assertEqual(slice(None, None, -2).indices(10), (9, -1, -2))
153 self.assertEqual(slice(3, None, -2).indices(10), (3, -1, -2)) 162 self.assertEqual(slice(3, None, -2).indices(10), (3, -1, -2))
154 # issue 3004 tests 163 # issue 3004 tests
155 self.assertEqual(slice(None, -9).indices(10), (0, 1, 1)) 164 self.assertEqual(slice(None, -9).indices(10), (0, 1, 1))
(...skipping 18 matching lines...) Expand all
174 slice(None, None, -1).indices(10) 183 slice(None, None, -1).indices(10)
175 ) 184 )
176 self.assertEqual(slice(-100, 100, 2).indices(10), (0, 10, 2)) 185 self.assertEqual(slice(-100, 100, 2).indices(10), (0, 10, 2))
177 186
178 self.assertEqual(list(range(10))[::sys.maxsize - 1], [0]) 187 self.assertEqual(list(range(10))[::sys.maxsize - 1], [0])
179 188
180 # Check a variety of start, stop, step and length values, including 189 # Check a variety of start, stop, step and length values, including
181 # values exceeding sys.maxsize (see issue #14794). 190 # 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] 191 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] 192 lengths = [0, 1, 7, 53, 2**30, 2**100]
184 for start in vals: 193 for slice_args in itertools.product(vals, repeat=3):
185 for stop in vals: 194 s = slice(*slice_args)
186 for step in vals: 195 for length in lengths:
187 s = slice(start, stop, step) 196 self.check_indices(s, length)
188 for length in lengths: 197 self.check_indices(slice(0, 10, 1), -3)
189 self.check_indices(s, length)
190 198
191 # Negative length should raise ValueError 199 # Negative length should raise ValueError
192 with self.assertRaises(ValueError): 200 with self.assertRaises(ValueError):
193 slice(None).indices(-1) 201 slice(None).indices(-1)
194 202
195 # Zero step should raise ValueError 203 # Zero step should raise ValueError
196 with self.assertRaises(ValueError): 204 with self.assertRaises(ValueError):
197 slice(0, 10, 0).indices(5) 205 slice(0, 10, 0).indices(5)
198 206
199 # Using a start, stop or step or length that can't be interpreted as an 207 # Using a start, stop or step or length that can't be interpreted as an
(...skipping 30 matching lines...) Expand all
230 t = loads(dumps(s, protocol)) 238 t = loads(dumps(s, protocol))
231 self.assertEqual(s, t) 239 self.assertEqual(s, t)
232 self.assertEqual(s.indices(15), t.indices(15)) 240 self.assertEqual(s.indices(15), t.indices(15))
233 self.assertNotEqual(id(s), id(t)) 241 self.assertNotEqual(id(s), id(t))
234 242
235 def test_main(): 243 def test_main():
236 support.run_unittest(SliceTest) 244 support.run_unittest(SliceTest)
237 245
238 if __name__ == "__main__": 246 if __name__ == "__main__":
239 test_main() 247 test_main()
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+