Merge pull request #805 from Ryex/ryex-list.__setitem__

implement  list.__setitem__ with slice and int indexing
This commit is contained in:
Adam
2019-04-09 10:24:48 +01:00
committed by GitHub
3 changed files with 485 additions and 20 deletions

View File

@@ -201,3 +201,280 @@ assert_raises(TypeError, bad_del_1)
def bad_del_2():
del ['a', 'b'][2]
assert_raises(IndexError, bad_del_2)
# __setitem__
# simple index
x = [1, 2, 3, 4, 5]
x[0] = 'a'
assert x == ['a', 2, 3, 4, 5]
x[-1] = 'b'
assert x == ['a', 2, 3, 4, 'b']
# make sure refrences are assigned correctly
y = []
x[1] = y
y.append(100)
assert x[1] == y
assert x[1] == [100]
#index bounds
def set_index_out_of_bounds_high():
x = [0, 1, 2, 3, 4]
x[5] = 'a'
def set_index_out_of_bounds_low():
x = [0, 1, 2, 3, 4]
x[-6] = 'a'
assert_raises(IndexError, set_index_out_of_bounds_high)
assert_raises(IndexError, set_index_out_of_bounds_low)
# non stepped slice index
a = list(range(10))
x = a[:]
y = a[:]
assert x == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# replace whole list
x[:] = ['a', 'b', 'c']
y[::1] = ['a', 'b', 'c']
assert x == ['a', 'b', 'c']
assert x == y
# splice list start
x = a[:]
y = a[:]
z = a[:]
zz = a[:]
x[:1] = ['a', 'b', 'c']
y[0:1] = ['a', 'b', 'c']
z[:1:1] = ['a', 'b', 'c']
zz[0:1:1] = ['a', 'b', 'c']
assert x == ['a', 'b', 'c', 1, 2, 3, 4, 5, 6, 7, 8, 9]
assert x == y
assert x == z
assert x == zz
# splice list end
x = a[:]
y = a[:]
z = a[:]
zz = a[:]
x[5:] = ['a', 'b', 'c']
y[5::1] = ['a', 'b', 'c']
z[5:10] = ['a', 'b', 'c']
zz[5:10:1] = ['a', 'b', 'c']
assert x == [0, 1, 2, 3, 4, 'a', 'b', 'c']
assert x == y
assert x == z
assert x == zz
# insert sec
x = a[:]
y = a[:]
z = a[:]
zz = a[:]
x[1:1] = ['a', 'b', 'c']
y[1:0] = ['a', 'b', 'c']
z[1:1:1] = ['a', 'b', 'c']
zz[1:0:1] = ['a', 'b', 'c']
assert x == [0, 'a', 'b', 'c', 1, 2, 3, 4, 5, 6, 7, 8, 9]
assert x == y
assert x == z
assert x == zz
# same but negative indexes?
x = a[:]
y = a[:]
z = a[:]
zz = a[:]
x[-1:-1] = ['a', 'b', 'c']
y[-1:9] = ['a', 'b', 'c']
z[-1:-1:1] = ['a', 'b', 'c']
zz[-1:9:1] = ['a', 'b', 'c']
assert x == [0, 1, 2, 3, 4, 5, 6, 7, 8, 'a', 'b', 'c', 9]
assert x == y
assert x == z
assert x == zz
# splice mid
x = a[:]
y = a[:]
x[3:5] = ['a', 'b', 'c', 'd', 'e']
y[3:5:1] = ['a', 'b', 'c', 'd', 'e']
assert x == [0, 1, 2, 'a', 'b', 'c', 'd', 'e', 5, 6, 7, 8, 9]
assert x == y
x = a[:]
x[3:5] = ['a']
assert x == [0, 1, 2, 'a', 5, 6, 7, 8, 9]
# assign empty to non stepped empty slice does nothing
x = a[:]
y = a[:]
x[5:2] = []
y[5:2:1] = []
assert x == a
assert y == a
# assign empty to non stepped slice removes elems
x = a[:]
y = a[:]
x[2:8] = []
y[2:8:1] = []
assert x == [0, 1, 8, 9]
assert x == y
# make sure refrences are assigned correctly
yy = []
x = a[:]
y = a[:]
x[3:5] = ['a', 'b', 'c', 'd', yy]
y[3:5:1] = ['a', 'b', 'c', 'd', yy]
assert x == [0, 1, 2, 'a', 'b', 'c', 'd', [], 5, 6, 7, 8, 9]
assert x == y
yy.append(100)
assert x == [0, 1, 2, 'a', 'b', 'c', 'd', [100], 5, 6, 7, 8, 9]
assert x == y
assert x[7] == yy
assert x[7] == [100]
assert y[7] == yy
assert y[7] == [100]
# no zero step
def no_zero_step_set():
x = [1, 2, 3, 4, 5]
x[0:4:0] = [11, 12, 13, 14, 15]
assert_raises(ValueError, no_zero_step_set)
# stepped slice index
# forward slice
x = a[:]
x[2:8:2] = ['a', 'b', 'c']
assert x == [0, 1, 'a', 3, 'b', 5, 'c', 7, 8, 9]
x = a[:]
y = a[:]
z = a[:]
zz = a[:]
c = ['a', 'b', 'c', 'd', 'e']
x[::2] = c
y[-10::2] = c
z[0:10:2] = c
zz[-13:13:2] = c # slice indexes will be truncated to bounds
assert x == ['a', 1, 'b', 3, 'c', 5, 'd', 7, 'e', 9]
assert x == y
assert x == z
assert x == zz
# backward slice
x = a[:]
x[8:2:-2] = ['a', 'b', 'c']
assert x == [0, 1, 2, 3, 'c', 5, 'b', 7, 'a', 9]
x = a[:]
y = a[:]
z = a[:]
zz = a[:]
c = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
x[::-1] = c
y[9:-11:-1] = c
z[9::-1] = c
zz[11:-13:-1] = c # slice indexes will be truncated to bounds
assert x == ['j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
assert x == y
assert x == z
assert x == zz
# step size bigger than len
x = a[:]
x[::200] = ['a']
assert x == ['a', 1, 2, 3, 4, 5, 6, 7, 8, 9]
x = a[:]
x[5::200] = ['a']
assert x == [0, 1, 2, 3, 4, 'a', 6, 7, 8, 9]
# bad stepped slices
def stepped_slice_assign_too_big():
x = [0, 1, 2, 3, 4]
x[::2] = ['a', 'b', 'c', 'd']
assert_raises(ValueError, stepped_slice_assign_too_big)
def stepped_slice_assign_too_small():
x = [0, 1, 2, 3, 4]
x[::2] = ['a', 'b']
assert_raises(ValueError, stepped_slice_assign_too_small)
# must assign iter t0 slice
def must_assign_iter_to_slice():
x = [0, 1, 2, 3, 4]
x[::2] = 42
assert_raises(TypeError, must_assign_iter_to_slice)
# other iterables?
a = list(range(10))
# string
x = a[:]
x[3:8] = "abcdefghi"
assert x == [0, 1, 2, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 8, 9]
# tuple
x = a[:]
x[3:8] = (11, 12, 13, 14, 15)
assert x == [0, 1, 2, 11, 12, 13, 14, 15, 8, 9]
# class
# __next__
class CIterNext:
def __init__(self, sec=(1, 2, 3)):
self.sec = sec
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.sec):
raise StopIteration
v = self.sec[self.index]
self.index += 1
return v
x = list(range(10))
x[3:8] = CIterNext()
assert x == [0, 1, 2, 1, 2, 3, 8, 9]
# __iter__ yield
class CIter:
def __init__(self, sec=(1, 2, 3)):
self.sec = sec
def __iter__(self):
for n in self.sec:
yield n
x = list(range(10))
x[3:8] = CIter()
assert x == [0, 1, 2, 1, 2, 3, 8, 9]
# __getitem but no __iter__ sequence
class CGetItem:
def __init__(self, sec=(1, 2, 3)):
self.sec = sec
def __getitem__(self, sub):
return self.sec[sub]
x = list(range(10))
x[3:8] = CGetItem()
assert x == [0, 1, 2, 1, 2, 3, 8, 9]
# iter raises error
class CIterError:
def __iter__(self):
for i in range(10):
if i > 5:
raise RuntimeError
yield i
def bad_iter_assign():
x = list(range(10))
x[3:8] = CIterError()
assert_raises(RuntimeError, bad_iter_assign)
# slice assign when step or stop is -1
a = list(range(10))
x = a[:]
x[-1:-5:-1] = ['a', 'b', 'c', 'd']
assert x == [0, 1, 2, 3, 4, 5, 'd', 'c', 'b', 'a']
x = a[:]
x[-5:-1:-1] = []
assert x == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]