diff --git a/src/ytdl_sub/downloaders/youtube/channel.py b/src/ytdl_sub/downloaders/youtube/channel.py index bfa3ac2a..b86365d5 100644 --- a/src/ytdl_sub/downloaders/youtube/channel.py +++ b/src/ytdl_sub/downloaders/youtube/channel.py @@ -15,7 +15,6 @@ from ytdl_sub.utils.thumbnail import convert_url_thumbnail from ytdl_sub.validators.date_range_validator import DateRangeValidator from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator from ytdl_sub.validators.url_validator import YoutubeChannelUrlValidator -from ytdl_sub.validators.validators import BoolValidator from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive logger = Logger.get() @@ -49,7 +48,6 @@ class YoutubeChannelDownloaderOptions(YoutubeDownloaderOptions, DateRangeValidat "after", "channel_avatar_path", "channel_banner_path", - "download_individually", } def __init__(self, name, value): @@ -64,9 +62,6 @@ class YoutubeChannelDownloaderOptions(YoutubeDownloaderOptions, DateRangeValidat self._channel_banner_path = self._validate_key_if_present( "channel_banner_path", OverridesStringFormatterValidator ) - self._download_individually = self._validate_key_if_present( - "download_individually", BoolValidator, default=True - ) @property def channel_url(self) -> str: @@ -91,15 +86,6 @@ class YoutubeChannelDownloaderOptions(YoutubeDownloaderOptions, DateRangeValidat """ return self._channel_banner_path - @property - def download_individually(self) -> Optional[bool]: - """ - Optional. Downloads files from the channel individually instead of in bulk. Setting to True - is safer when downloading large amounts of videos in case an error occurs. Downloading by - bulk (by setting to False) can increase speeds. Defaults to True. - """ - return self._download_individually.value - class YoutubeChannelDownloader(YoutubeDownloader[YoutubeChannelDownloaderOptions, YoutubeVideo]): downloader_options_type = YoutubeChannelDownloaderOptions @@ -155,26 +141,26 @@ class YoutubeChannelDownloader(YoutubeDownloader[YoutubeChannelDownloaderOptions """ ytdl_options_overrides = {} - # If downloading individually, dry-run the entire channel download first, this will get the - # videos that will be downloaded. Afterwards, download each video one-by-one - if self.download_options.download_individually: - ytdl_options_overrides["skip_download"] = True - ytdl_options_overrides["writethumbnail"] = False - # If a date range is specified when download a YT channel, add it into the ytdl options source_date_range = self.download_options.get_date_range() if source_date_range: ytdl_options_overrides["daterange"] = source_date_range + # dry-run the entire channel download first, this will get the + # videos that will be downloaded. Afterwards, download each video one-by-one entry_dicts = self.extract_info_via_info_json( - ytdl_options_overrides=ytdl_options_overrides, url=self.download_options.channel_url + ytdl_options_overrides=dict( + {"skip_download": True, "write_thumbnail": False}, **ytdl_options_overrides + ), + url=self.download_options.channel_url, ) self.channel = self._get_channel_from_entry_dicts(entry_dicts=entry_dicts) for entry_dict in entry_dicts: if entry_dict.get("extractor") == "youtube": - # Only do the individual download if it is not dry-run and downloading individually - if not self.is_dry_run and self.download_options.download_individually: + # Only do the individual download if it is not dry-run + # TODO: Respect the Reject/Exist exceptions + if not self.is_dry_run: ytdl_options_overrides["playlist_items"] = str(entry_dict.get("playlist_index")) _ = self.extract_info( ytdl_options_overrides={ diff --git a/src/ytdl_sub/downloaders/youtube/playlist.py b/src/ytdl_sub/downloaders/youtube/playlist.py index 1a476dba..21fe2f9e 100644 --- a/src/ytdl_sub/downloaders/youtube/playlist.py +++ b/src/ytdl_sub/downloaders/youtube/playlist.py @@ -1,12 +1,10 @@ from typing import Dict from typing import Generator -from typing import Optional from ytdl_sub.downloaders.youtube.abc import YoutubeDownloader from ytdl_sub.downloaders.youtube.abc import YoutubeDownloaderOptions from ytdl_sub.entries.youtube import YoutubePlaylistVideo from ytdl_sub.validators.url_validator import YoutubePlaylistUrlValidator -from ytdl_sub.validators.validators import BoolValidator class YoutubePlaylistDownloaderOptions(YoutubeDownloaderOptions): @@ -28,16 +26,12 @@ class YoutubePlaylistDownloaderOptions(YoutubeDownloaderOptions): """ _required_keys = {"playlist_url"} - _optional_keys = {"download_individually"} def __init__(self, name, value): super().__init__(name, value) self._playlist_url = self._validate_key( "playlist_url", YoutubePlaylistUrlValidator ).playlist_url - self._download_individually = self._validate_key_if_present( - "download_individually", BoolValidator, default=True - ) @property def playlist_url(self) -> str: @@ -47,15 +41,6 @@ class YoutubePlaylistDownloaderOptions(YoutubeDownloaderOptions): """ return self._playlist_url - @property - def download_individually(self) -> Optional[bool]: - """ - Optional. Downloads files from the playlist individually instead of in bulk. Setting to True - is safer when downloading large amounts of videos in case an error occurs. Downloading by - bulk (by setting to False) can increase speeds. Defaults to True. - """ - return self._download_individually.value - class YoutubePlaylistDownloader( YoutubeDownloader[YoutubePlaylistDownloaderOptions, YoutubePlaylistVideo] @@ -84,25 +69,24 @@ class YoutubePlaylistDownloader( def download(self) -> Generator[YoutubePlaylistVideo, None, None]: """ - Downloads all videos in a Youtube playlist + Downloads all videos in a Youtube playlist. + + Dry-run the entire playlist download first. This will get the videos that will be + downloaded. Afterwards, download each video one-by-one """ - ytdl_options_overrides = {} - - # If downloading individually, dry-run the entire channel download first, this will get the - # videos that will be downloaded. Afterwards, download each video one-by-one - if self.download_options.download_individually: - ytdl_options_overrides["skip_download"] = True - ytdl_options_overrides["writethumbnail"] = False - entry_dicts = self.extract_info_via_info_json( - ytdl_options_overrides=ytdl_options_overrides, url=self.download_options.playlist_url + ytdl_options_overrides={ + "skip_download": True, + "writethumbnail": False, + }, + url=self.download_options.playlist_url, ) for entry_dict in entry_dicts: if entry_dict.get("extractor") == "youtube": # Only do the individual download if it is not dry-run and downloading individually - if not self.is_dry_run and self.download_options.download_individually: + if not self.is_dry_run: _ = self.extract_info( ytdl_options_overrides={ "playlist_items": str(entry_dict.get("playlist_index")), diff --git a/tests/e2e/youtube/test_channel_as_kodi_tv_show.py b/tests/e2e/youtube/test_channel_as_kodi_tv_show.py index 9f2f2bdc..9fe5257f 100644 --- a/tests/e2e/youtube/test_channel_as_kodi_tv_show.py +++ b/tests/e2e/youtube/test_channel_as_kodi_tv_show.py @@ -225,7 +225,6 @@ class TestChannelAsKodiTvShow: """ @pytest.mark.parametrize("dry_run", [True, False]) - @pytest.mark.parametrize("download_individually", [True, False]) def test_full_channel_download( self, channel_subscription_generator, @@ -233,10 +232,7 @@ class TestChannelAsKodiTvShow: expected_full_channel_download, output_directory, dry_run, - download_individually, ): - channel_preset_dict["youtube"]["download_individually"] = download_individually - full_channel_subscription = channel_subscription_generator(preset_dict=channel_preset_dict) transaction_log = full_channel_subscription.download(dry_run=dry_run) assert_transaction_log_matches( @@ -248,7 +244,6 @@ class TestChannelAsKodiTvShow: expected_full_channel_download.assert_files_exist(relative_directory=output_directory) @pytest.mark.parametrize("dry_run", [True, False]) - @pytest.mark.parametrize("download_individually", [True, False]) def test_recent_channel_download( self, channel_subscription_generator, @@ -256,10 +251,7 @@ class TestChannelAsKodiTvShow: expected_recent_channel_download, output_directory, dry_run, - download_individually, ): - recent_channel_preset_dict["youtube"]["download_individually"] = download_individually - recent_channel_subscription = channel_subscription_generator( preset_dict=recent_channel_preset_dict ) @@ -291,7 +283,6 @@ class TestChannelAsKodiTvShow: ) @pytest.mark.parametrize("dry_run", [True, False]) - @pytest.mark.parametrize("download_individually", [True, False]) def test_recent_channel_download__no_vids_in_range( self, channel_subscription_generator, @@ -299,9 +290,7 @@ class TestChannelAsKodiTvShow: expected_recent_channel_no_vids_in_range_download, output_directory, dry_run, - download_individually, ): - recent_channel_preset_dict["youtube"]["download_individually"] = download_individually recent_channel_preset_dict["youtube"]["after"] = "21000101" recent_channel_no_vids_in_range_subscription = channel_subscription_generator( @@ -321,7 +310,6 @@ class TestChannelAsKodiTvShow: ) @pytest.mark.parametrize("dry_run", [True, False]) - @pytest.mark.parametrize("download_individually", [True, False]) def test_rolling_recent_channel_download( self, channel_subscription_generator, @@ -331,13 +319,7 @@ class TestChannelAsKodiTvShow: expected_rolling_recent_channel_download, output_directory, dry_run, - download_individually, ): - recent_channel_preset_dict["youtube"]["download_individually"] = download_individually - rolling_recent_channel_preset_dict["youtube"][ - "download_individually" - ] = download_individually - recent_channel_subscription = channel_subscription_generator( preset_dict=recent_channel_preset_dict ) diff --git a/tests/e2e/youtube/test_playlist_as_kodi_music_videos.py b/tests/e2e/youtube/test_playlist_as_kodi_music_videos.py index a3e3471c..035adbf2 100644 --- a/tests/e2e/youtube/test_playlist_as_kodi_music_videos.py +++ b/tests/e2e/youtube/test_playlist_as_kodi_music_videos.py @@ -92,7 +92,6 @@ class TestPlaylistAsKodiMusicVideo: """ @pytest.mark.parametrize("dry_run", [True, False]) - @pytest.mark.parametrize("download_individually", [True, False]) def test_playlist_download( self, music_video_config, @@ -100,10 +99,7 @@ class TestPlaylistAsKodiMusicVideo: expected_playlist_download, output_directory, dry_run, - download_individually, ): - playlist_preset_dict["youtube"]["download_individually"] = download_individually - playlist_subscription = Subscription.from_dict( config=music_video_config, preset_name="music_video_playlist_test",