@ -3954,10 +3954,14 @@ class LazyList(collections.Sequence):
def __init__ ( self , iterable ) :
def __init__ ( self , iterable ) :
self . __iterable = iter ( iterable )
self . __iterable = iter ( iterable )
self . __cache = [ ]
self . __cache = [ ]
self . __reversed = False
def __iter__ ( self ) :
def __iter__ ( self ) :
for item in self . __cache :
if self . __reversed :
yield item
# We need to consume the entire iterable to iterate in reverse
yield from self . exhaust ( ) [ : : - 1 ]
return
yield from self . __cache
for item in self . __iterable :
for item in self . __iterable :
self . __cache . append ( item )
self . __cache . append ( item )
yield item
yield item
@ -3965,21 +3969,31 @@ class LazyList(collections.Sequence):
def exhaust ( self ) :
def exhaust ( self ) :
''' Evaluate the entire iterable '''
''' Evaluate the entire iterable '''
self . __cache . extend ( self . __iterable )
self . __cache . extend ( self . __iterable )
return self . __cache
@staticmethod
def _reverse_index ( x ) :
return - ( x + 1 )
def __getitem__ ( self , idx ) :
def __getitem__ ( self , idx ) :
if isinstance ( idx , slice ) :
if isinstance ( idx , slice ) :
step = idx . step or 1
step = idx . step or 1
start = idx . start if idx . start is not None else 1 if step > 0 else - 1
start = idx . start if idx . start is not None else 0 if step > 0 else - 1
stop = idx . stop if idx . stop is not None else - 1 if step > 0 else 0
stop = idx . stop if idx . stop is not None else - 1 if step > 0 else 0
if self . __reversed :
start , stop , step = map ( self . _reverse_index , ( start , stop , step ) )
idx = slice ( start , stop , step )
elif isinstance ( idx , int ) :
elif isinstance ( idx , int ) :
if self . __reversed :
idx = self . _reverse_index ( idx )
start = stop = idx
start = stop = idx
else :
else :
raise TypeError ( ' indices must be integers or slices ' )
raise TypeError ( ' indices must be integers or slices ' )
if start < 0 or stop < 0 :
if start < 0 or stop < 0 :
# We need to consume the entire iterable to be able to slice from the end
# We need to consume the entire iterable to be able to slice from the end
# Obviously, never use this with infinite iterables
# Obviously, never use this with infinite iterables
self . exhaust ( )
return self . exhaust ( ) [ idx ]
else :
n = max ( start , stop ) - len ( self . __cache ) + 1
n = max ( start , stop ) - len ( self . __cache ) + 1
if n > 0 :
if n > 0 :
self . __cache . extend ( itertools . islice ( self . __iterable , n ) )
self . __cache . extend ( itertools . islice ( self . __iterable , n ) )
@ -3987,7 +4001,7 @@ class LazyList(collections.Sequence):
def __bool__ ( self ) :
def __bool__ ( self ) :
try :
try :
self [ 0 ]
self [ - 1 ] if self . __reversed else self [ 0 ]
except IndexError :
except IndexError :
return False
return False
return True
return True
@ -3996,6 +4010,17 @@ class LazyList(collections.Sequence):
self . exhaust ( )
self . exhaust ( )
return len ( self . __cache )
return len ( self . __cache )
def __reversed__ ( self ) :
self . __reversed = not self . __reversed
return self
def __repr__ ( self ) :
# repr and str should mimic a list. So we exhaust the iterable
return repr ( self . exhaust ( ) )
def __str__ ( self ) :
return repr ( self . exhaust ( ) )
class PagedList ( object ) :
class PagedList ( object ) :
def __len__ ( self ) :
def __len__ ( self ) :