Skip to content

Commit 512a7e4

Browse files
committed
fixes for islice
1 parent b51df0f commit 512a7e4

File tree

1 file changed

+75
-10
lines changed

1 file changed

+75
-10
lines changed

graalpython/lib-graalpython/itertools.py

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -159,23 +159,88 @@ def __next__(self):
159159
class islice(object):
160160
@__graalpython__.builtin_method
161161
def __init__(self, iterable, *args):
162-
self._iterable = enumerate(iter(iterable))
163-
slice = list(args)
164-
if len(slice) >= 2 and slice[1] is None:
165-
slice[1] = sys.maxsize
166-
self._indexes = iter(range(*slice))
162+
start = 0
163+
stop = -1
164+
step = 1
165+
if len(args) not in [1, 2, 3]:
166+
raise TypeError("islice(seq, stop) or islice(seq, start, stop[, step])")
167+
if len(args) == 1:
168+
if args[0] != None:
169+
stop = int(args[0])
170+
else:
171+
if args[0] != None:
172+
try:
173+
start = int(args[0])
174+
except:
175+
start = -1
176+
if args[1] != None:
177+
try:
178+
stop = int(args[1])
179+
except:
180+
raise ValueError("Stop argument for islice() must be None or ean integer: 0 <= x <= sys.maxsize.")
181+
if start < 0 or stop < -1 or start > sys.maxsize or stop > sys.maxsize:
182+
raise ValueError("Indices for islice() must be None or an integer: 0 <= x <= sys.maxsize.")
183+
if len(args) == 3:
184+
if args[2] != None:
185+
try:
186+
step = int(args[2])
187+
except:
188+
step = -1
189+
if step < 1:
190+
raise ValueError("Step for islice() must be a positive integer or None.")
191+
192+
self._it = iter(iterable)
193+
self._next = start
194+
self._stop = stop
195+
self._step = step
196+
self._cnt = 0
167197

168198
@__graalpython__.builtin_method
169199
def __iter__(self):
170200
return self
171201

172202
@__graalpython__.builtin_method
173203
def __next__(self):
174-
index = next(self._indexes) # may raise StopIteration
175-
while True:
176-
i, element = next(self._iterable) # may raise StopIteration
177-
if i == index:
178-
return element
204+
it = self._it
205+
stop = self._stop
206+
if not it:
207+
raise StopIteration
208+
while self._cnt < self._next:
209+
try:
210+
item = next(it)
211+
except:
212+
# C code uses any exception to clear the iterator
213+
self._it = None
214+
raise
215+
self._cnt += 1
216+
if stop != -1 and self._cnt >= stop:
217+
self._it = None
218+
raise StopIteration
219+
try:
220+
item = next(it)
221+
except:
222+
self._it = None
223+
raise
224+
self._cnt += 1
225+
oldnext = self._next
226+
self._next += self._step
227+
if self._next < oldnext or (stop != -1 and self._next > stop):
228+
self._next = stop
229+
return item
230+
231+
@__graalpython__.builtin_method
232+
def __reduce__(self):
233+
if self._it is None:
234+
return type(self), (iter([]), 0), 0
235+
if self._stop == -1:
236+
stop = None
237+
else:
238+
stop = self._stop
239+
return type(self), (self._it, self._next, stop, self._step), self._cnt
240+
241+
@__graalpython__.builtin_method
242+
def __setstate__(self, state):
243+
self._cnt = int(state)
179244

180245

181246
class count(object):

0 commit comments

Comments
 (0)