aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--yt_dlp/utils.py50
1 files changed, 50 insertions, 0 deletions
diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py
index ec8f007d5..02a12307a 100644
--- a/yt_dlp/utils.py
+++ b/yt_dlp/utils.py
@@ -3945,6 +3945,56 @@ def detect_exe_version(output, version_re=None, unrecognized='present'):
return unrecognized
+class LazyList(collections.Sequence):
+ ''' Lazy immutable list from an iterable
+ Note that slices of a LazyList are lists and not LazyList'''
+
+ def __init__(self, iterable):
+ self.__iterable = iter(iterable)
+ self.__cache = []
+
+ def __iter__(self):
+ for item in self.__cache:
+ yield item
+ for item in self.__iterable:
+ self.__cache.append(item)
+ yield item
+
+ def exhaust(self):
+ ''' Evaluate the entire iterable '''
+ self.__cache.extend(self.__iterable)
+
+ def __getitem__(self, idx):
+ if isinstance(idx, slice):
+ step = idx.step or 1
+ start = idx.start if idx.start is not None else 1 if step > 0 else -1
+ stop = idx.stop if idx.stop is not None else -1 if step > 0 else 0
+ elif isinstance(idx, int):
+ start = stop = idx
+ else:
+ raise TypeError('indices must be integers or slices')
+ if start < 0 or stop < 0:
+ # We need to consume the entire iterable to be able to slice from the end
+ # Obviously, never use this with infinite iterables
+ self.exhaust()
+ else:
+ n = max(start, stop) - len(self.__cache) + 1
+ if n > 0:
+ self.__cache.extend(itertools.islice(self.__iterable, n))
+ return self.__cache[idx]
+
+ def __bool__(self):
+ try:
+ self[0]
+ except IndexError:
+ return False
+ return True
+
+ def __len__(self):
+ self.exhaust()
+ return len(self.__cache)
+
+
class PagedList(object):
def __len__(self):
# This is only useful for tests