import re from typing import Set import pytest from expected_download import assert_expected_downloads from expected_transaction_log import assert_transaction_log_matches from ytdl_sub.config.config_file import ConfigFile from ytdl_sub.prebuilt_presets.tv_show import TvShowByDatePresets from ytdl_sub.script.utils.exceptions import UserThrownRuntimeError from ytdl_sub.subscriptions.subscription import Subscription DEFAULT_SEASON_ORDERING = "upload-year" DEFAULT_EPISODE_ORDERING = "upload-month-day" VALID_ORDERING_COMBOS = [ # upload ("upload-year", "upload-month-day"), ("upload-year", "upload-month-day-reversed"), ("upload-year", "download-index"), ("upload-year-month", "upload-day"), # release ("release-year", "release-month-day"), ("release-year", "release-month-day-reversed"), ("release-year", "download-index"), ("release-year-month", "release-day"), ] class TestPrebuiltTVShowPresets: @staticmethod def run( config: ConfigFile, subscription_name: str, output_directory: str, tv_show_preset: str, season_ordering: str, episode_ordering: str, is_youtube_channel: bool = True, is_many_urls: bool = False, ): expected_summary_name = "integration/by-date/{}/{}/{}/is_yt_{}{}".format( tv_show_preset.split(" ")[0], season_ordering, episode_ordering, int(is_youtube_channel), "_many_urls" if is_many_urls else "", ) preset_dict = { "preset": tv_show_preset, "overrides": { "url": "https://your.name.here", "tv_show_name": "Best Prebuilt TV Show by Date", "tv_show_directory": output_directory, "tv_show_by_date_season_ordering": season_ordering, "tv_show_by_date_episode_ordering": episode_ordering, }, } if is_many_urls: preset_dict["overrides"]["url2"] = "https://url.number.2.here" subscription = Subscription.from_dict( config=config, preset_name=subscription_name, preset_dict=preset_dict, ) transaction_log = subscription.download(dry_run=False) assert_transaction_log_matches( output_directory=output_directory, transaction_log=transaction_log, transaction_log_summary_file_name=f"{expected_summary_name}.txt", ) assert_expected_downloads( output_directory=output_directory, dry_run=False, expected_download_summary_file_name=f"{expected_summary_name}.json", ) ###################################### Perform reformat reformatted_season_ordering = "upload-year" reformatted_episode_ordering = "download-index" reformatted_expected_summary_name = "integration/by-date/{}/{}/{}/is_yt_{}{}".format( tv_show_preset.split(" ")[0], reformatted_season_ordering, reformatted_episode_ordering, int(is_youtube_channel), "_many_urls" if is_many_urls else "", ) reformatted_preset_dict = { "preset": tv_show_preset, "output_options": { "migrated_download_archive_name": ".ytdl-sub-{tv_show_name_sanitized}-download-archive.json" }, "overrides": { "url": "https://your.name.here", "tv_show_name": "Best Prebuilt TV Show by Date", "tv_show_directory": output_directory, "tv_show_by_date_season_ordering": reformatted_season_ordering, "tv_show_by_date_episode_ordering": reformatted_episode_ordering, }, } if is_many_urls: reformatted_preset_dict["overrides"]["url2"] = "https://url.number.2.here" reformatted_subscription = Subscription.from_dict( config=config, preset_name=subscription_name, preset_dict=reformatted_preset_dict ) reformatted_transaction_log = reformatted_subscription.update_with_info_json(dry_run=False) assert_transaction_log_matches( output_directory=output_directory, transaction_log=reformatted_transaction_log, transaction_log_summary_file_name=( f"{expected_summary_name}_reformatted_to_{reformatted_season_ordering}.txt" ), ) assert_expected_downloads( output_directory=output_directory, dry_run=False, expected_download_summary_file_name=f"{reformatted_expected_summary_name}_migrated.json", ) @pytest.mark.parametrize("tv_show_preset", TvShowByDatePresets.preset_names) def test_tv_show_presets( self, config, subscription_name, output_directory, mock_download_collection_entries, tv_show_preset: str, ): with mock_download_collection_entries(is_youtube_channel=True): self.run( config=config, subscription_name=subscription_name, output_directory=output_directory, tv_show_preset=tv_show_preset, season_ordering=DEFAULT_SEASON_ORDERING, episode_ordering=DEFAULT_EPISODE_ORDERING, ) @pytest.mark.parametrize( "season_ordering, episode_ordering", VALID_ORDERING_COMBOS, ) def test_episode_ordering_presets( self, config, subscription_name, output_directory, mock_download_collection_entries, season_ordering: str, episode_ordering: str, ): with mock_download_collection_entries( is_youtube_channel=True, ): self.run( config=config, subscription_name=subscription_name, output_directory=output_directory, tv_show_preset="Kodi TV Show by Date", season_ordering=season_ordering, episode_ordering=episode_ordering, ) def test_invalid_season_ordering( self, config, subscription_name, output_directory, mock_download_collection_entries ): expected_message = ( "tv_show_by_date_season_ordering must be one of the following: " '"upload-year", ' '"upload-year-month", ' '"release-year", ' '"release-year-month"' ) with ( mock_download_collection_entries(is_youtube_channel=True, num_urls=1), pytest.raises(UserThrownRuntimeError, match=re.escape(expected_message)), ): self.run( config=config, subscription_name=subscription_name, output_directory=output_directory, tv_show_preset="Kodi TV Show by Date", season_ordering="nope", episode_ordering=DEFAULT_EPISODE_ORDERING, ) def test_invalid_episode_ordering( self, config, subscription_name, output_directory, mock_download_collection_entries ): expected_message = ( "tv_show_by_date_episode_ordering must be one of the following: " '"upload-day", ' '"upload-month-day", ' '"upload-month-day-reversed", ' '"release-day", ' '"release-month-day", ' '"release-month-day-reversed", ' '"download-index"' ) with ( mock_download_collection_entries(is_youtube_channel=True, num_urls=1), pytest.raises(UserThrownRuntimeError, match=re.escape(expected_message)), ): self.run( config=config, subscription_name=subscription_name, output_directory=output_directory, tv_show_preset="Kodi TV Show by Date", season_ordering=DEFAULT_SEASON_ORDERING, episode_ordering="not-a-valid", ) def test_invalid_season_episode_ordering_combo( self, config, subscription_name, output_directory, mock_download_collection_entries ): expected_message = ( "Detected incompatibility between tv_show_by_date_season_ordering " "and tv_show_by_date_episode_ordering. Ensure you are not using both " "upload and release date, and that the year/month/day are included in " "the combined season and episode." ) possible_seasons: Set[str] = set() possible_episodes: Set[str] = set() for season_ordering, episode_ordering in VALID_ORDERING_COMBOS: possible_seasons.add(season_ordering) possible_episodes.add(episode_ordering) for season_ordering in possible_seasons: for episode_ordering in possible_episodes: if (season_ordering, episode_ordering) in VALID_ORDERING_COMBOS: continue with ( mock_download_collection_entries(is_youtube_channel=True, num_urls=1), pytest.raises(UserThrownRuntimeError, match=re.escape(expected_message)), ): self.run( config=config, subscription_name=subscription_name, output_directory=output_directory, tv_show_preset="Kodi TV Show by Date", season_ordering=season_ordering, episode_ordering=episode_ordering, )