Skip to content

Commit 39042e6

Browse files
authored
Merge pull request RustPython#805 from Ryex/ryex-list.__setitem__
implement list.__setitem__ with slice and int indexing
2 parents 958a0a2 + b2a1f65 commit 39042e6

File tree

3 files changed

+484
-19
lines changed

3 files changed

+484
-19
lines changed

tests/snippets/list.py

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,280 @@ def bad_del_1():
201201
def bad_del_2():
202202
del ['a', 'b'][2]
203203
assert_raises(IndexError, bad_del_2)
204+
205+
# __setitem__
206+
207+
# simple index
208+
x = [1, 2, 3, 4, 5]
209+
x[0] = 'a'
210+
assert x == ['a', 2, 3, 4, 5]
211+
x[-1] = 'b'
212+
assert x == ['a', 2, 3, 4, 'b']
213+
# make sure refrences are assigned correctly
214+
y = []
215+
x[1] = y
216+
y.append(100)
217+
assert x[1] == y
218+
assert x[1] == [100]
219+
220+
#index bounds
221+
def set_index_out_of_bounds_high():
222+
x = [0, 1, 2, 3, 4]
223+
x[5] = 'a'
224+
225+
def set_index_out_of_bounds_low():
226+
x = [0, 1, 2, 3, 4]
227+
x[-6] = 'a'
228+
229+
assert_raises(IndexError, set_index_out_of_bounds_high)
230+
assert_raises(IndexError, set_index_out_of_bounds_low)
231+
232+
# non stepped slice index
233+
a = list(range(10))
234+
x = a[:]
235+
y = a[:]
236+
assert x == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
237+
# replace whole list
238+
x[:] = ['a', 'b', 'c']
239+
y[::1] = ['a', 'b', 'c']
240+
assert x == ['a', 'b', 'c']
241+
assert x == y
242+
# splice list start
243+
x = a[:]
244+
y = a[:]
245+
z = a[:]
246+
zz = a[:]
247+
x[:1] = ['a', 'b', 'c']
248+
y[0:1] = ['a', 'b', 'c']
249+
z[:1:1] = ['a', 'b', 'c']
250+
zz[0:1:1] = ['a', 'b', 'c']
251+
assert x == ['a', 'b', 'c', 1, 2, 3, 4, 5, 6, 7, 8, 9]
252+
assert x == y
253+
assert x == z
254+
assert x == zz
255+
# splice list end
256+
x = a[:]
257+
y = a[:]
258+
z = a[:]
259+
zz = a[:]
260+
x[5:] = ['a', 'b', 'c']
261+
y[5::1] = ['a', 'b', 'c']
262+
z[5:10] = ['a', 'b', 'c']
263+
zz[5:10:1] = ['a', 'b', 'c']
264+
assert x == [0, 1, 2, 3, 4, 'a', 'b', 'c']
265+
assert x == y
266+
assert x == z
267+
assert x == zz
268+
# insert sec
269+
x = a[:]
270+
y = a[:]
271+
z = a[:]
272+
zz = a[:]
273+
x[1:1] = ['a', 'b', 'c']
274+
y[1:0] = ['a', 'b', 'c']
275+
z[1:1:1] = ['a', 'b', 'c']
276+
zz[1:0:1] = ['a', 'b', 'c']
277+
assert x == [0, 'a', 'b', 'c', 1, 2, 3, 4, 5, 6, 7, 8, 9]
278+
assert x == y
279+
assert x == z
280+
assert x == zz
281+
# same but negative indexes?
282+
x = a[:]
283+
y = a[:]
284+
z = a[:]
285+
zz = a[:]
286+
x[-1:-1] = ['a', 'b', 'c']
287+
y[-1:9] = ['a', 'b', 'c']
288+
z[-1:-1:1] = ['a', 'b', 'c']
289+
zz[-1:9:1] = ['a', 'b', 'c']
290+
assert x == [0, 1, 2, 3, 4, 5, 6, 7, 8, 'a', 'b', 'c', 9]
291+
assert x == y
292+
assert x == z
293+
assert x == zz
294+
# splice mid
295+
x = a[:]
296+
y = a[:]
297+
x[3:5] = ['a', 'b', 'c', 'd', 'e']
298+
y[3:5:1] = ['a', 'b', 'c', 'd', 'e']
299+
assert x == [0, 1, 2, 'a', 'b', 'c', 'd', 'e', 5, 6, 7, 8, 9]
300+
assert x == y
301+
x = a[:]
302+
x[3:5] = ['a']
303+
assert x == [0, 1, 2, 'a', 5, 6, 7, 8, 9]
304+
# assign empty to non stepped empty slice does nothing
305+
x = a[:]
306+
y = a[:]
307+
x[5:2] = []
308+
y[5:2:1] = []
309+
assert x == a
310+
assert y == a
311+
# assign empty to non stepped slice removes elems
312+
x = a[:]
313+
y = a[:]
314+
x[2:8] = []
315+
y[2:8:1] = []
316+
assert x == [0, 1, 8, 9]
317+
assert x == y
318+
# make sure refrences are assigned correctly
319+
yy = []
320+
x = a[:]
321+
y = a[:]
322+
x[3:5] = ['a', 'b', 'c', 'd', yy]
323+
y[3:5:1] = ['a', 'b', 'c', 'd', yy]
324+
assert x == [0, 1, 2, 'a', 'b', 'c', 'd', [], 5, 6, 7, 8, 9]
325+
assert x == y
326+
yy.append(100)
327+
assert x == [0, 1, 2, 'a', 'b', 'c', 'd', [100], 5, 6, 7, 8, 9]
328+
assert x == y
329+
assert x[7] == yy
330+
assert x[7] == [100]
331+
assert y[7] == yy
332+
assert y[7] == [100]
333+
334+
# no zero step
335+
def no_zero_step_set():
336+
x = [1, 2, 3, 4, 5]
337+
x[0:4:0] = [11, 12, 13, 14, 15]
338+
assert_raises(ValueError, no_zero_step_set)
339+
340+
# stepped slice index
341+
# forward slice
342+
x = a[:]
343+
x[2:8:2] = ['a', 'b', 'c']
344+
assert x == [0, 1, 'a', 3, 'b', 5, 'c', 7, 8, 9]
345+
x = a[:]
346+
y = a[:]
347+
z = a[:]
348+
zz = a[:]
349+
c = ['a', 'b', 'c', 'd', 'e']
350+
x[::2] = c
351+
y[-10::2] = c
352+
z[0:10:2] = c
353+
zz[-13:13:2] = c # slice indexes will be truncated to bounds
354+
assert x == ['a', 1, 'b', 3, 'c', 5, 'd', 7, 'e', 9]
355+
assert x == y
356+
assert x == z
357+
assert x == zz
358+
# backward slice
359+
x = a[:]
360+
x[8:2:-2] = ['a', 'b', 'c']
361+
assert x == [0, 1, 2, 3, 'c', 5, 'b', 7, 'a', 9]
362+
x = a[:]
363+
y = a[:]
364+
z = a[:]
365+
zz = a[:]
366+
c = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
367+
x[::-1] = c
368+
y[9:-11:-1] = c
369+
z[9::-1] = c
370+
zz[11:-13:-1] = c # slice indexes will be truncated to bounds
371+
assert x == ['j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
372+
assert x == y
373+
assert x == z
374+
assert x == zz
375+
# step size bigger than len
376+
x = a[:]
377+
x[::200] = ['a']
378+
assert x == ['a', 1, 2, 3, 4, 5, 6, 7, 8, 9]
379+
x = a[:]
380+
x[5::200] = ['a']
381+
assert x == [0, 1, 2, 3, 4, 'a', 6, 7, 8, 9]
382+
383+
# bad stepped slices
384+
def stepped_slice_assign_too_big():
385+
x = [0, 1, 2, 3, 4]
386+
x[::2] = ['a', 'b', 'c', 'd']
387+
388+
assert_raises(ValueError, stepped_slice_assign_too_big)
389+
390+
def stepped_slice_assign_too_small():
391+
x = [0, 1, 2, 3, 4]
392+
x[::2] = ['a', 'b']
393+
394+
assert_raises(ValueError, stepped_slice_assign_too_small)
395+
396+
# must assign iter t0 slice
397+
def must_assign_iter_to_slice():
398+
x = [0, 1, 2, 3, 4]
399+
x[::2] = 42
400+
401+
assert_raises(TypeError, must_assign_iter_to_slice)
402+
403+
# other iterables?
404+
a = list(range(10))
405+
406+
# string
407+
x = a[:]
408+
x[3:8] = "abcdefghi"
409+
assert x == [0, 1, 2, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 8, 9]
410+
411+
# tuple
412+
x = a[:]
413+
x[3:8] = (11, 12, 13, 14, 15)
414+
assert x == [0, 1, 2, 11, 12, 13, 14, 15, 8, 9]
415+
416+
# class
417+
# __next__
418+
class CIterNext:
419+
def __init__(self, sec=(1, 2, 3)):
420+
self.sec = sec
421+
self.index = 0
422+
def __iter__(self):
423+
return self
424+
def __next__(self):
425+
if self.index >= len(self.sec):
426+
raise StopIteration
427+
v = self.sec[self.index]
428+
self.index += 1
429+
return v
430+
431+
x = list(range(10))
432+
x[3:8] = CIterNext()
433+
assert x == [0, 1, 2, 1, 2, 3, 8, 9]
434+
435+
# __iter__ yield
436+
class CIter:
437+
def __init__(self, sec=(1, 2, 3)):
438+
self.sec = sec
439+
def __iter__(self):
440+
for n in self.sec:
441+
yield n
442+
443+
x = list(range(10))
444+
x[3:8] = CIter()
445+
assert x == [0, 1, 2, 1, 2, 3, 8, 9]
446+
447+
# __getitem but no __iter__ sequence
448+
class CGetItem:
449+
def __init__(self, sec=(1, 2, 3)):
450+
self.sec = sec
451+
def __getitem__(self, sub):
452+
return self.sec[sub]
453+
454+
x = list(range(10))
455+
x[3:8] = CGetItem()
456+
assert x == [0, 1, 2, 1, 2, 3, 8, 9]
457+
458+
# iter raises error
459+
class CIterError:
460+
def __iter__(self):
461+
for i in range(10):
462+
if i > 5:
463+
raise RuntimeError
464+
yield i
465+
466+
def bad_iter_assign():
467+
x = list(range(10))
468+
x[3:8] = CIterError()
469+
470+
assert_raises(RuntimeError, bad_iter_assign)
471+
472+
# slice assign when step or stop is -1
473+
474+
a = list(range(10))
475+
x = a[:]
476+
x[-1:-5:-1] = ['a', 'b', 'c', 'd']
477+
assert x == [0, 1, 2, 3, 4, 5, 'd', 'c', 'b', 'a']
478+
x = a[:]
479+
x[-5:-1:-1] = []
480+
assert x == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

0 commit comments

Comments
 (0)