Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DEV] More OutputOption unit tests #1082

Merged
merged 8 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ytdl_sub/cli/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def _download_subscription_from_cli(
extra_arguments=extra_args, config_options=config.config_options
)
subscription_args_dict = dl_args_parser.to_subscription_dict()
subscription_name = f"cli-dl-{dl_args_parser.get_args_hash()}"
subscription_name = dl_args_parser.get_dl_subscription_name()

subscription = Subscription.from_dict(
config=config, preset_name=subscription_name, preset_dict=subscription_args_dict
Expand Down
9 changes: 5 additions & 4 deletions src/ytdl_sub/cli/parsers/dl.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,13 @@ def to_subscription_dict(self) -> Dict:

return subscription_dict

def get_args_hash(self) -> str:
def get_dl_subscription_name(self) -> str:
"""
:return: Hash of the arguments provided
Returns a deterministic name based on input args
"""
hash_string = str(sorted(self._unknown_arguments))
return hashlib.sha256(hash_string.encode()).hexdigest()[-8:]
to_hash = str(sorted(self._unknown_arguments))
hash_str = hashlib.sha256(to_hash.encode()).hexdigest()[-8:]
return f"cli-dl-{hash_str}"

@classmethod
def from_dl_override(cls, override: str, config: ConfigFile) -> "DownloadArgsParser":
Expand Down
10 changes: 10 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
import json
import logging
import os
import shlex
import shutil
import sys
import tempfile
from pathlib import Path
from typing import Any
Expand All @@ -18,8 +20,10 @@
from resources import file_fixture_path
from yt_dlp.utils import sanitize_filename

from ytdl_sub.cli.entrypoint import main
from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.entries.script.custom_functions import CustomFunctions
from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.subscriptions.subscription_download import SubscriptionDownload
from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.logger import Logger
Expand Down Expand Up @@ -262,3 +266,9 @@ def default_config_path(default_config) -> str:
@pytest.fixture()
def music_subscriptions_path() -> Path:
return Path("examples/music_subscriptions.yaml")


def mock_run_from_cli(args: str) -> List[Subscription]:
args_list = ["ytdl-sub"] + shlex.split(args)
with patch.object(sys, "argv", args_list):
return main()
12 changes: 0 additions & 12 deletions tests/e2e/conftest.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import shlex
import sys
import tempfile
from typing import List
from unittest.mock import patch

import pytest

from ytdl_sub.cli.entrypoint import main
from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.utils.file_handler import FileHandler


Expand All @@ -31,9 +25,3 @@ def timestamps_file_path():
yield tmp.name
finally:
FileHandler.delete(tmp.name)


def mock_run_from_cli(args: str) -> List[Subscription]:
args_list = ["ytdl-sub"] + shlex.split(args)
with patch.object(sys, "argv", args_list):
return main()
2 changes: 1 addition & 1 deletion tests/e2e/plugins/internal/test_view.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Optional

import pytest
from e2e.conftest import mock_run_from_cli
from conftest import mock_run_from_cli

from ytdl_sub.utils.file_handler import FileMetadata

Expand Down
128 changes: 0 additions & 128 deletions tests/e2e/youtube/test_playlist.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
from pathlib import Path
from typing import Dict

import pytest
from conftest import assert_logs
from e2e.conftest import mock_run_from_cli
from expected_download import assert_expected_downloads
from expected_transaction_log import assert_transaction_log_matches
from mergedeep import mergedeep

from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.downloaders.ytdlp import YTDLP
from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.utils.system import IS_WINDOWS


@pytest.fixture
Expand Down Expand Up @@ -100,50 +96,6 @@ class TestPlaylist:
files exist and have the expected md5 file hashes.
"""

@classmethod
def _ensure_subscription_migrates(
cls,
config: ConfigFile,
subscription_name: str,
subscription_dict: Dict,
output_directory: Path,
):
# Ensure download archive migrates
mergedeep.merge(
subscription_dict,
{
"output_options": {
"migrated_download_archive_name": ".ytdl-sub-{tv_show_name_sanitized}-download-archive.json"
}
},
)
migrated_subscription = Subscription.from_dict(
config=config,
preset_name=subscription_name,
preset_dict=subscription_dict,
)
transaction_log = migrated_subscription.download()

assert_transaction_log_matches(
output_directory=output_directory,
transaction_log=transaction_log,
transaction_log_summary_file_name="youtube/test_playlist_archive_migrated.txt",
)
assert_expected_downloads(
output_directory=output_directory,
dry_run=False,
expected_download_summary_file_name="youtube/test_playlist_archive_migrated.json",
)

# Ensure no changes after migration
transaction_log = migrated_subscription.download()
assert transaction_log.is_empty
assert_expected_downloads(
output_directory=output_directory,
dry_run=False,
expected_download_summary_file_name="youtube/test_playlist_archive_migrated.json",
)

@pytest.mark.parametrize("dry_run", [True, False])
def test_playlist_download(
self,
Expand Down Expand Up @@ -186,86 +138,6 @@ def test_playlist_download(
expected_download_summary_file_name="youtube/test_playlist.json",
)

self._ensure_subscription_migrates(
config=default_config,
subscription_name="music_video_playlist_test",
subscription_dict=playlist_preset_dict,
output_directory=output_directory,
)

@pytest.mark.parametrize("dry_run", [True, False])
def test_playlist_download_from_cli_sub_no_provided_config(
self,
preset_dict_to_subscription_yaml_generator,
playlist_preset_dict,
output_directory,
dry_run,
):
# TODO: Fix CLI parsing on windows when dealing with spaces
if IS_WINDOWS:
return

# No config needed when using only prebuilt presets
with preset_dict_to_subscription_yaml_generator(
subscription_name="music_video_playlist_test", preset_dict=playlist_preset_dict
) as subscription_path:
args = "--dry-run " if dry_run else ""
args += f"sub '{subscription_path}'"
subscriptions = mock_run_from_cli(args=args)

assert len(subscriptions) == 1
transaction_log = subscriptions[0].transaction_log

assert_transaction_log_matches(
output_directory=output_directory,
transaction_log=transaction_log,
transaction_log_summary_file_name="youtube/test_playlist.txt",
)
assert_expected_downloads(
output_directory=output_directory,
dry_run=dry_run,
expected_download_summary_file_name="youtube/test_playlist.json",
)

if not dry_run:
# Ensure another invocation will hit ExistingVideoReached
with assert_logs(
logger=YTDLP.logger,
expected_message="ExistingVideoReached, stopping additional downloads",
log_level="debug",
):
transaction_log = mock_run_from_cli(args=args)[0].transaction_log

assert transaction_log.is_empty
assert_expected_downloads(
output_directory=output_directory,
dry_run=dry_run,
expected_download_summary_file_name="youtube/test_playlist.json",
)

def test_playlist_download_from_cli_sub_with_override_arg(
self,
preset_dict_to_subscription_yaml_generator,
playlist_preset_dict,
output_directory,
):
# TODO: Fix CLI parsing on windows when dealing with spaces
if IS_WINDOWS:
return

# No config needed when using only prebuilt presets
with preset_dict_to_subscription_yaml_generator(
subscription_name="music_video_playlist_test", preset_dict=playlist_preset_dict
) as subscription_path:
args = (
f"--dry-run sub '{subscription_path}' --dl-override '--date_range.after 20240101'"
)

subscriptions = mock_run_from_cli(args=args)

assert len(subscriptions) == 1
assert subscriptions[0].transaction_log.is_empty

def test_tv_show_by_date_downloads_bilateral(
self,
tv_show_by_date_bilateral_dict: Dict,
Expand Down
77 changes: 0 additions & 77 deletions tests/e2e/youtube/test_video.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
from unittest.mock import patch

import pytest
from conftest import preset_dict_to_dl_args
from e2e.conftest import mock_run_from_cli
from expected_download import assert_expected_downloads
from expected_transaction_log import assert_transaction_log_matches

from ytdl_sub.downloaders.ytdlp import YTDLP
from ytdl_sub.entries.entry import Entry
from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.system import IS_WINDOWS
from ytdl_sub.utils.thumbnail import try_convert_download_thumbnail


@pytest.fixture
Expand Down Expand Up @@ -69,72 +61,3 @@ def test_single_video_download(
dry_run=dry_run,
expected_download_summary_file_name="youtube/test_video.json",
)

def test_single_video_download_missing_thumbnail(
self,
default_config,
single_video_preset_dict,
working_directory,
output_directory,
):
single_video_subscription = Subscription.from_dict(
config=default_config,
preset_name="music_video_single_video_test",
preset_dict=single_video_preset_dict,
)

def delete_entry_thumb(entry: Entry) -> None:
FileHandler.delete(entry.get_download_thumbnail_path())
try_convert_download_thumbnail(entry=entry)

# Pretend the thumbnail did not download via returning nothing for its downloaded path
with (
patch.object(YTDLP, "_EXTRACT_ENTRY_NUM_RETRIES", 1),
patch.object(Entry, "try_get_ytdlp_download_thumbnail_path") as mock_ytdlp_path,
patch(
"ytdl_sub.downloaders.url.downloader.try_convert_download_thumbnail",
side_effect=delete_entry_thumb,
),
):
mock_ytdlp_path.return_value = None
transaction_log = single_video_subscription.download(dry_run=False)

assert_transaction_log_matches(
output_directory=output_directory,
transaction_log=transaction_log,
transaction_log_summary_file_name="youtube/test_video_missing_thumb.txt",
)
assert_expected_downloads(
output_directory=output_directory,
dry_run=False,
expected_download_summary_file_name="youtube/test_video_missing_thumb.json",
)

@pytest.mark.parametrize("dry_run", [True, False])
def test_single_video_download_from_cli_dl(
self,
default_config_path,
single_video_preset_dict_dl_args,
output_directory,
dry_run,
):
# TODO: Fix CLI parsing on windows when dealing with spaces
if IS_WINDOWS:
return

args = "--dry-run " if dry_run else ""
args += f"--config {default_config_path} "
args += f"dl {single_video_preset_dict_dl_args}"
subscriptions = mock_run_from_cli(args=args)

assert len(subscriptions) == 1
assert_transaction_log_matches(
output_directory=output_directory,
transaction_log=subscriptions[0].transaction_log,
transaction_log_summary_file_name="youtube/test_video_cli.txt",
)
assert_expected_downloads(
output_directory=output_directory,
dry_run=dry_run,
expected_download_summary_file_name="youtube/test_video_cli.json",
)
Loading
Loading