Adds the ability to change season and episode ordering using override variables, like so:
```
"~Kids Toys Play":
url: "https://www.youtube.com/@KidsToysPlayChannel"
tv_show_by_date_season_ordering: "upload-year-month"
tv_show_by_date_episode_ordering: "upload-day"
```
In addition, adds support for release-date based episode ordering (and culling if using Only Recent).
More info here: https://ytdl-sub.readthedocs.io/en/latest/prebuilt_presets/tv_shows.html
Closes https://github.com/jmbannon/ytdl-sub/issues/1182
259 lines
9.4 KiB
Python
259 lines
9.4 KiB
Python
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,
|
|
)
|