diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py index cf8304c39..9768bb8ca 100644 --- a/yt_dlp/YoutubeDL.py +++ b/yt_dlp/YoutubeDL.py @@ -1211,7 +1211,8 @@ class YoutubeDL(object): else: self.report_error('no suitable InfoExtractor for URL %s' % url) - def __handle_extraction_exceptions(func, handle_all_errors=True): + def __handle_extraction_exceptions(func): + def wrapper(self, *args, **kwargs): try: return func(self, *args, **kwargs) @@ -1228,10 +1229,10 @@ class YoutubeDL(object): self.to_stderr('\r') self.report_warning('The download speed is below throttle limit. Re-extracting data') return wrapper(self, *args, **kwargs) - except (MaxDownloadsReached, ExistingVideoReached, RejectedVideoReached): + except (MaxDownloadsReached, ExistingVideoReached, RejectedVideoReached, LazyList.IndexError): raise except Exception as e: - if handle_all_errors and self.params.get('ignoreerrors', False): + if self.params.get('ignoreerrors', False): self.report_error(error_to_compat_str(e), tb=encode_compat_str(traceback.format_exc())) else: raise @@ -1436,14 +1437,18 @@ class YoutubeDL(object): msg = ( 'Downloading %d videos' if not isinstance(ie_entries, list) else 'Collected %d videos; downloading %%d of them' % len(ie_entries)) - if not isinstance(ie_entries, (list, PagedList)): - ie_entries = LazyList(ie_entries) - - def get_entry(i): - return YoutubeDL.__handle_extraction_exceptions( - lambda self, i: ie_entries[i - 1], - False - )(self, i) + + if isinstance(ie_entries, list): + def get_entry(i): + return ie_entries[i - 1] + else: + if not isinstance(ie_entries, PagedList): + ie_entries = LazyList(ie_entries) + + def get_entry(i): + return YoutubeDL.__handle_extraction_exceptions( + lambda self, i: ie_entries[i - 1] + )(self, i) entries = [] for i in playlistitems or itertools.count(playliststart): diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py index fa9c509b2..65d585d05 100644 --- a/yt_dlp/utils.py +++ b/yt_dlp/utils.py @@ -3972,6 +3972,9 @@ class LazyList(collections.abc.Sequence): ''' Lazy immutable list from an iterable Note that slices of a LazyList are lists and not LazyList''' + class IndexError(IndexError): + pass + def __init__(self, iterable): self.__iterable = iter(iterable) self.__cache = [] @@ -4015,22 +4018,28 @@ class LazyList(collections.abc.Sequence): or (stop is None and step > 0)): # We need to consume the entire iterable to be able to slice from the end # Obviously, never use this with infinite iterables - return self.__exhaust()[idx] - + self.__exhaust() + try: + return self.__cache[idx] + except IndexError as e: + raise self.IndexError(e) from e n = max(start or 0, stop or 0) - len(self.__cache) + 1 if n > 0: self.__cache.extend(itertools.islice(self.__iterable, n)) - return self.__cache[idx] + try: + return self.__cache[idx] + except IndexError as e: + raise self.IndexError(e) from e def __bool__(self): try: self[-1] if self.__reversed else self[0] - except IndexError: + except self.IndexError: return False return True def __len__(self): - self.exhaust() + self.__exhaust() return len(self.__cache) def reverse(self):