[BACKEND] Remove individual_download parameter from youtube channel + playlist (#119)

This commit is contained in:
Jesse Bannon 2022-07-22 08:46:05 -07:00 committed by GitHub
parent 72442ab846
commit d292ab0510
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 71 deletions

View file

@ -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.date_range_validator import DateRangeValidator
from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator
from ytdl_sub.validators.url_validator import YoutubeChannelUrlValidator 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 from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive
logger = Logger.get() logger = Logger.get()
@ -49,7 +48,6 @@ class YoutubeChannelDownloaderOptions(YoutubeDownloaderOptions, DateRangeValidat
"after", "after",
"channel_avatar_path", "channel_avatar_path",
"channel_banner_path", "channel_banner_path",
"download_individually",
} }
def __init__(self, name, value): def __init__(self, name, value):
@ -64,9 +62,6 @@ class YoutubeChannelDownloaderOptions(YoutubeDownloaderOptions, DateRangeValidat
self._channel_banner_path = self._validate_key_if_present( self._channel_banner_path = self._validate_key_if_present(
"channel_banner_path", OverridesStringFormatterValidator "channel_banner_path", OverridesStringFormatterValidator
) )
self._download_individually = self._validate_key_if_present(
"download_individually", BoolValidator, default=True
)
@property @property
def channel_url(self) -> str: def channel_url(self) -> str:
@ -91,15 +86,6 @@ class YoutubeChannelDownloaderOptions(YoutubeDownloaderOptions, DateRangeValidat
""" """
return self._channel_banner_path 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]): class YoutubeChannelDownloader(YoutubeDownloader[YoutubeChannelDownloaderOptions, YoutubeVideo]):
downloader_options_type = YoutubeChannelDownloaderOptions downloader_options_type = YoutubeChannelDownloaderOptions
@ -155,26 +141,26 @@ class YoutubeChannelDownloader(YoutubeDownloader[YoutubeChannelDownloaderOptions
""" """
ytdl_options_overrides = {} 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 # 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() source_date_range = self.download_options.get_date_range()
if source_date_range: if source_date_range:
ytdl_options_overrides["daterange"] = 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( 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) self.channel = self._get_channel_from_entry_dicts(entry_dicts=entry_dicts)
for entry_dict in entry_dicts: for entry_dict in entry_dicts:
if entry_dict.get("extractor") == "youtube": if entry_dict.get("extractor") == "youtube":
# Only do the individual download if it is not dry-run and downloading individually # Only do the individual download if it is not dry-run
if not self.is_dry_run and self.download_options.download_individually: # TODO: Respect the Reject/Exist exceptions
if not self.is_dry_run:
ytdl_options_overrides["playlist_items"] = str(entry_dict.get("playlist_index")) ytdl_options_overrides["playlist_items"] = str(entry_dict.get("playlist_index"))
_ = self.extract_info( _ = self.extract_info(
ytdl_options_overrides={ ytdl_options_overrides={

View file

@ -1,12 +1,10 @@
from typing import Dict from typing import Dict
from typing import Generator from typing import Generator
from typing import Optional
from ytdl_sub.downloaders.youtube.abc import YoutubeDownloader from ytdl_sub.downloaders.youtube.abc import YoutubeDownloader
from ytdl_sub.downloaders.youtube.abc import YoutubeDownloaderOptions from ytdl_sub.downloaders.youtube.abc import YoutubeDownloaderOptions
from ytdl_sub.entries.youtube import YoutubePlaylistVideo from ytdl_sub.entries.youtube import YoutubePlaylistVideo
from ytdl_sub.validators.url_validator import YoutubePlaylistUrlValidator from ytdl_sub.validators.url_validator import YoutubePlaylistUrlValidator
from ytdl_sub.validators.validators import BoolValidator
class YoutubePlaylistDownloaderOptions(YoutubeDownloaderOptions): class YoutubePlaylistDownloaderOptions(YoutubeDownloaderOptions):
@ -28,16 +26,12 @@ class YoutubePlaylistDownloaderOptions(YoutubeDownloaderOptions):
""" """
_required_keys = {"playlist_url"} _required_keys = {"playlist_url"}
_optional_keys = {"download_individually"}
def __init__(self, name, value): def __init__(self, name, value):
super().__init__(name, value) super().__init__(name, value)
self._playlist_url = self._validate_key( self._playlist_url = self._validate_key(
"playlist_url", YoutubePlaylistUrlValidator "playlist_url", YoutubePlaylistUrlValidator
).playlist_url ).playlist_url
self._download_individually = self._validate_key_if_present(
"download_individually", BoolValidator, default=True
)
@property @property
def playlist_url(self) -> str: def playlist_url(self) -> str:
@ -47,15 +41,6 @@ class YoutubePlaylistDownloaderOptions(YoutubeDownloaderOptions):
""" """
return self._playlist_url 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( class YoutubePlaylistDownloader(
YoutubeDownloader[YoutubePlaylistDownloaderOptions, YoutubePlaylistVideo] YoutubeDownloader[YoutubePlaylistDownloaderOptions, YoutubePlaylistVideo]
@ -84,25 +69,24 @@ class YoutubePlaylistDownloader(
def download(self) -> Generator[YoutubePlaylistVideo, None, None]: 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( 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: for entry_dict in entry_dicts:
if entry_dict.get("extractor") == "youtube": if entry_dict.get("extractor") == "youtube":
# Only do the individual download if it is not dry-run and downloading individually # 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( _ = self.extract_info(
ytdl_options_overrides={ ytdl_options_overrides={
"playlist_items": str(entry_dict.get("playlist_index")), "playlist_items": str(entry_dict.get("playlist_index")),

View file

@ -225,7 +225,6 @@ class TestChannelAsKodiTvShow:
""" """
@pytest.mark.parametrize("dry_run", [True, False]) @pytest.mark.parametrize("dry_run", [True, False])
@pytest.mark.parametrize("download_individually", [True, False])
def test_full_channel_download( def test_full_channel_download(
self, self,
channel_subscription_generator, channel_subscription_generator,
@ -233,10 +232,7 @@ class TestChannelAsKodiTvShow:
expected_full_channel_download, expected_full_channel_download,
output_directory, output_directory,
dry_run, dry_run,
download_individually,
): ):
channel_preset_dict["youtube"]["download_individually"] = download_individually
full_channel_subscription = channel_subscription_generator(preset_dict=channel_preset_dict) full_channel_subscription = channel_subscription_generator(preset_dict=channel_preset_dict)
transaction_log = full_channel_subscription.download(dry_run=dry_run) transaction_log = full_channel_subscription.download(dry_run=dry_run)
assert_transaction_log_matches( assert_transaction_log_matches(
@ -248,7 +244,6 @@ class TestChannelAsKodiTvShow:
expected_full_channel_download.assert_files_exist(relative_directory=output_directory) expected_full_channel_download.assert_files_exist(relative_directory=output_directory)
@pytest.mark.parametrize("dry_run", [True, False]) @pytest.mark.parametrize("dry_run", [True, False])
@pytest.mark.parametrize("download_individually", [True, False])
def test_recent_channel_download( def test_recent_channel_download(
self, self,
channel_subscription_generator, channel_subscription_generator,
@ -256,10 +251,7 @@ class TestChannelAsKodiTvShow:
expected_recent_channel_download, expected_recent_channel_download,
output_directory, output_directory,
dry_run, dry_run,
download_individually,
): ):
recent_channel_preset_dict["youtube"]["download_individually"] = download_individually
recent_channel_subscription = channel_subscription_generator( recent_channel_subscription = channel_subscription_generator(
preset_dict=recent_channel_preset_dict preset_dict=recent_channel_preset_dict
) )
@ -291,7 +283,6 @@ class TestChannelAsKodiTvShow:
) )
@pytest.mark.parametrize("dry_run", [True, False]) @pytest.mark.parametrize("dry_run", [True, False])
@pytest.mark.parametrize("download_individually", [True, False])
def test_recent_channel_download__no_vids_in_range( def test_recent_channel_download__no_vids_in_range(
self, self,
channel_subscription_generator, channel_subscription_generator,
@ -299,9 +290,7 @@ class TestChannelAsKodiTvShow:
expected_recent_channel_no_vids_in_range_download, expected_recent_channel_no_vids_in_range_download,
output_directory, output_directory,
dry_run, dry_run,
download_individually,
): ):
recent_channel_preset_dict["youtube"]["download_individually"] = download_individually
recent_channel_preset_dict["youtube"]["after"] = "21000101" recent_channel_preset_dict["youtube"]["after"] = "21000101"
recent_channel_no_vids_in_range_subscription = channel_subscription_generator( 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("dry_run", [True, False])
@pytest.mark.parametrize("download_individually", [True, False])
def test_rolling_recent_channel_download( def test_rolling_recent_channel_download(
self, self,
channel_subscription_generator, channel_subscription_generator,
@ -331,13 +319,7 @@ class TestChannelAsKodiTvShow:
expected_rolling_recent_channel_download, expected_rolling_recent_channel_download,
output_directory, output_directory,
dry_run, 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( recent_channel_subscription = channel_subscription_generator(
preset_dict=recent_channel_preset_dict preset_dict=recent_channel_preset_dict
) )

View file

@ -92,7 +92,6 @@ class TestPlaylistAsKodiMusicVideo:
""" """
@pytest.mark.parametrize("dry_run", [True, False]) @pytest.mark.parametrize("dry_run", [True, False])
@pytest.mark.parametrize("download_individually", [True, False])
def test_playlist_download( def test_playlist_download(
self, self,
music_video_config, music_video_config,
@ -100,10 +99,7 @@ class TestPlaylistAsKodiMusicVideo:
expected_playlist_download, expected_playlist_download,
output_directory, output_directory,
dry_run, dry_run,
download_individually,
): ):
playlist_preset_dict["youtube"]["download_individually"] = download_individually
playlist_subscription = Subscription.from_dict( playlist_subscription = Subscription.from_dict(
config=music_video_config, config=music_video_config,
preset_name="music_video_playlist_test", preset_name="music_video_playlist_test",