test in place
This commit is contained in:
parent
96bdd30a7e
commit
cc170a1c13
5 changed files with 63 additions and 253 deletions
|
|
@ -15,8 +15,9 @@ from ytdl_sub.cli.output_transaction_log import (
|
|||
)
|
||||
from ytdl_sub.cli.parsers.cli_to_sub import print_cli_to_sub
|
||||
from ytdl_sub.cli.parsers.dl import DownloadArgsParser
|
||||
from ytdl_sub.cli.parsers.main import DEFAULT_CONFIG_FILE_NAME, InspectArguments, parser
|
||||
from ytdl_sub.cli.parsers.main import DEFAULT_CONFIG_FILE_NAME, parser
|
||||
from ytdl_sub.config.config_file import ConfigFile
|
||||
from ytdl_sub.config.validators.variable_validation import ResolutionLevel
|
||||
from ytdl_sub.subscriptions.subscription import Subscription
|
||||
from ytdl_sub.utils.exceptions import ExperimentalFeatureNotEnabled, ValidationException
|
||||
from ytdl_sub.utils.file_handler import FileHandler
|
||||
|
|
@ -215,14 +216,6 @@ def _parse_inspect_mocks(mocks: Optional[List[str]]) -> Dict[str, str]:
|
|||
return out
|
||||
|
||||
|
||||
def _parse_inspect_level(inspect_level: str) -> int:
|
||||
for val, name in InspectArguments.LevelChoices.items():
|
||||
if inspect_level == val or inspect_level == name:
|
||||
return int(val)
|
||||
|
||||
raise ValueError("should not reach here")
|
||||
|
||||
|
||||
def _inspect(
|
||||
config: ConfigFile,
|
||||
subscription_paths: List[str],
|
||||
|
|
@ -288,7 +281,7 @@ def main() -> List[Subscription]:
|
|||
subscription_paths=args.subscription_paths,
|
||||
subscription_matches=args.match,
|
||||
subscription_override_dict=subscription_override_dict,
|
||||
inspection_level=_parse_inspect_level(args.inspection_level),
|
||||
inspection_level=ResolutionLevel.level_number(args.inspection_level),
|
||||
mocks=_parse_inspect_mocks(args.mock),
|
||||
)
|
||||
return []
|
||||
|
|
|
|||
|
|
@ -266,12 +266,12 @@ inspect_parser.add_argument(
|
|||
metavar=",".join(str(i) for i in range(4)),
|
||||
type=str,
|
||||
help="""level of inspection to perform:
|
||||
0 - original present the subscription as-is (default)
|
||||
0 - original present the subscription as-is
|
||||
1 - fill fill in defined values
|
||||
2 - resolve resolve all variables
|
||||
2 - resolve resolve all possible variables (default)
|
||||
3 - internal resolve all variables to their internal representation
|
||||
""",
|
||||
default="0",
|
||||
default="resolve",
|
||||
choices=list(InspectArguments.LevelChoices.keys())
|
||||
+ list(InspectArguments.LevelChoices.values()),
|
||||
dest="inspection_level",
|
||||
|
|
|
|||
|
|
@ -35,6 +35,21 @@ class ResolutionLevel:
|
|||
return "internal"
|
||||
raise ValueError("Invalid resolution level")
|
||||
|
||||
@classmethod
|
||||
def level_number(cls, resolution_arg: str) -> int:
|
||||
"""
|
||||
Numeric resolution level
|
||||
"""
|
||||
if resolution_arg in ("0", "original"):
|
||||
return 0
|
||||
if resolution_arg in ("1", "fill"):
|
||||
return 1
|
||||
if resolution_arg in ("2", "resolve"):
|
||||
return 2
|
||||
if resolution_arg in ("3", "internal"):
|
||||
return 3
|
||||
raise ValueError("Invalid resolution level")
|
||||
|
||||
@classmethod
|
||||
def all(cls) -> List[int]:
|
||||
"""
|
||||
|
|
@ -81,8 +96,6 @@ class VariableValidation:
|
|||
unresolvable=self.unresolved_variables,
|
||||
)
|
||||
|
||||
|
||||
|
||||
self.script = self.script.resolve_partial(
|
||||
unresolvable=self.unresolved_variables,
|
||||
output_filter=self._get_resolve_partial_filter(),
|
||||
|
|
@ -132,9 +145,7 @@ class VariableValidation:
|
|||
value = self.script.definition_of(name)
|
||||
if name in self.script.function_names:
|
||||
# Keep custom functions as-is
|
||||
output[name] = self.overrides.dict_with_format_strings[
|
||||
name
|
||||
]
|
||||
output[name] = self.overrides.dict_with_format_strings[name]
|
||||
elif resolved := value.maybe_resolvable:
|
||||
output[name] = resolved.native
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -3,10 +3,16 @@ from pathlib import Path
|
|||
import pytest
|
||||
import yaml
|
||||
from conftest import mock_run_from_cli
|
||||
from unit.config.test_subscription_resolution import compare_resolved_yaml
|
||||
|
||||
from ytdl_sub.config.validators.variable_validation import ResolutionLevel
|
||||
|
||||
|
||||
class TestInspect:
|
||||
@pytest.mark.parametrize("config_provided", [True, False])
|
||||
@pytest.mark.parametrize(
|
||||
"inspect_level", ["0", "original", "1", "fill", "2", "resolve", "3", "internal"]
|
||||
)
|
||||
def test_inspect_command(
|
||||
self,
|
||||
capsys,
|
||||
|
|
@ -14,238 +20,21 @@ class TestInspect:
|
|||
tv_show_subscriptions_path: Path,
|
||||
output_directory: str,
|
||||
config_provided: bool,
|
||||
inspect_level: str,
|
||||
):
|
||||
# Shares same test fixture as `test_subscription_resolution.py`
|
||||
args = f"--config {default_config_path} " if config_provided else ""
|
||||
args += f"inspect {tv_show_subscriptions_path} --match 'Jake Trains'"
|
||||
args += f"inspect {tv_show_subscriptions_path} --match 'NOVA PBS' "
|
||||
args += f"--level {inspect_level}"
|
||||
|
||||
subscriptions = mock_run_from_cli(args=args)
|
||||
assert len(subscriptions) == 0
|
||||
|
||||
captured_as_dict = yaml.safe_load(capsys.readouterr().out)
|
||||
assert captured_as_dict == {
|
||||
"chapters": {
|
||||
"allow_chapters_from_comments": False,
|
||||
"embed_chapters": True,
|
||||
"enable": "True",
|
||||
"force_key_frames": False,
|
||||
},
|
||||
"date_range": {"breaks": "True", "enable": "True", "type": "upload_date"},
|
||||
"download": [
|
||||
{
|
||||
"download_reverse": "True",
|
||||
"include_sibling_metadata": False,
|
||||
"playlist_thumbnails": [
|
||||
{
|
||||
"name": "{avatar_uncropped_thumbnail_file_name}",
|
||||
"uid": "avatar_uncropped",
|
||||
},
|
||||
{
|
||||
"name": "{banner_uncropped_thumbnail_file_name}",
|
||||
"uid": "banner_uncropped",
|
||||
},
|
||||
],
|
||||
"source_thumbnails": [
|
||||
{
|
||||
"name": "{avatar_uncropped_thumbnail_file_name}",
|
||||
"uid": "avatar_uncropped",
|
||||
},
|
||||
{
|
||||
"name": "{banner_uncropped_thumbnail_file_name}",
|
||||
"uid": "banner_uncropped",
|
||||
},
|
||||
],
|
||||
"url": "https://www.youtube.com/@JakeTrains",
|
||||
"variables": {},
|
||||
"webpage_url": "{modified_webpage_url}",
|
||||
"ytdl_options": {},
|
||||
}
|
||||
],
|
||||
"file_convert": {"convert_to": "mp4", "convert_with": "yt-dlp", "enable": "True"},
|
||||
"format": "(bv*[ext=mp4][vcodec~='^((he|a)vc|h26[45])']+ba[ext=m4a]) / (bv[ext=mp4]*+ba[ext=m4a]/b)",
|
||||
"output_options": {
|
||||
"download_archive_name": ".ytdl-sub-Jake Trains-download-archive.json",
|
||||
"file_name": "{episode_file_path}.{ext}",
|
||||
"info_json_name": "{episode_file_path}.{info_json_ext}",
|
||||
"keep_files_date_eval": "{episode_date_standardized}",
|
||||
"maintain_download_archive": True,
|
||||
"output_directory": f"{output_directory}/Jake Trains",
|
||||
"preserve_mtime": False,
|
||||
"thumbnail_name": "{thumbnail_file_name}",
|
||||
},
|
||||
"overrides": {
|
||||
"%bilateral_url": "{ %if( %and( enable_bilateral_scraping, subscription_has_download_archive, %is_bilateral_url( $0 ) ), $0, '' ) }",
|
||||
"%episode_ordering_": "{ %eq( %lower( tv_show_by_date_episode_ordering ), $0 ) }",
|
||||
"%is_bilateral_url": '{ %contains( $0, "youtube.com/playlist" ) }',
|
||||
"%ordering_pair_eq": "{ %eq( [ tv_show_by_date_season_ordering, tv_show_by_date_episode_ordering ], [ $0, $1 ] ) }",
|
||||
"%season_ordering_": "{ %eq( %lower( tv_show_by_date_season_ordering ), $0 ) }",
|
||||
"assert_not_collection": '{ %assert( %and( %not( %bool( s01_url ) ), %not( %bool( s01_name ) ) ), "Provided `s01_url` or `s01_name` variable to TV Show by Date preset when it expects `url`. Perhaps you meant to use the `TV Show Collection` preset?" ) }',
|
||||
"avatar_uncropped_thumbnail_file_name": "{ tv_show_poster_file_name }",
|
||||
"banner_uncropped_thumbnail_file_name": "{ tv_show_fanart_file_name }",
|
||||
"enable_bilateral_scraping": "{ %bool(True) }",
|
||||
"enable_resolution_assert": "{ %bool(True) }",
|
||||
"enable_throttle_protection": "{ %bool(True) }",
|
||||
"episode_content_rating": "{ tv_show_content_rating }",
|
||||
"episode_date_standardized": '{ %if( %contains( tv_show_by_date_season_ordering, "release" ), release_date_standardized, upload_date_standardized ) }',
|
||||
"episode_file_name": '{ %concat( %string( "s" ), %string( season_number_padded ), %string( ".e" ), %string( episode_number_padded ), %string( " - " ), %string( file_title ) ) }',
|
||||
"episode_file_path": '{ %concat( %string( season_directory_name_sanitized ), %string( "/" ), %string( episode_file_name_sanitized ) ) }',
|
||||
"episode_number": "{ %array_at( episode_number_and_padded_, 0 ) }",
|
||||
"episode_number_and_padded_": '{ %elif( %episode_ordering_( "upload-day" ), [ %concat( upload_day, upload_date_index_padded ), 4 ], %episode_ordering_( "upload-month-day" ), [ %concat( upload_month, upload_day_padded, upload_date_index_padded ), 6 ], %episode_ordering_( "upload-month-day-reversed" ), [ %concat( upload_day_of_year_reversed, upload_date_index_reversed_padded ), 5 ], %episode_ordering_( "release-day" ), [ %concat( release_day, upload_date_index_padded ), 4 ], %episode_ordering_( "release-month-day" ), [ %concat( release_month, release_day_padded, upload_date_index_padded ), 6 ], %episode_ordering_( "release-month-day-reversed" ), [ %concat( release_day_of_year_reversed, upload_date_index_reversed_padded ), 5 ], %episode_ordering_( "download-index" ), [ download_index, 6 ], %throw( \'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"\' ) ) }',
|
||||
"episode_number_padded": "{ %pad_zero( %int( episode_number ), %int( %array_at( episode_number_and_padded_, 1 ) ) ) }",
|
||||
"episode_plot": '{ %concat( %string( webpage_url ), %string( "\n\n" ), %string( description ) ) }',
|
||||
"episode_title": '{ %concat( %string( episode_date_standardized ), %string( " - " ), %string( title ) ) }',
|
||||
"episode_year": "{ %slice( episode_date_standardized, 0, 4 ) }",
|
||||
"file_title": "{ title_sanitized_plex }",
|
||||
"file_uid": "{ uid_sanitized_plex }",
|
||||
"include_sibling_metadata": "{ %bool(False) }",
|
||||
"modified_webpage_url": "{ webpage_url }",
|
||||
"only_recent_date_range": "2months",
|
||||
"only_recent_max_files": "{ %int(30) }",
|
||||
"resolution_assert": '{ %if( %and( enable_resolution_assert, %ne( height, 0 ), %not( resolution_assert_is_ignored ) ), %assert( %gte( height, resolution_assert_height_gte ), %concat( "Entry ", title, " downloaded at a low resolution (", resolution_readable, "), you\'ve probably been throttled. ", "Stopping further downloads, wait a few hours and try again. ", "Disable using the override variable `enable_resolution_assert: False`." ) ), "false is no-op" ) }',
|
||||
"resolution_assert_height_gte": "{ %int(361) }",
|
||||
"resolution_assert_ignore_titles": "{ [ ] }",
|
||||
"resolution_assert_is_ignored": '{ %print_if_true( %concat( title, " has a match in resolution_assert_ignore_titles, skipping resolution assert." ), %contains_any( title, resolution_assert_ignore_titles ) ) }',
|
||||
"resolution_assert_print": '{ %print( %if( enable_resolution_assert, "Resolution assert is enabled, will fail on low-quality video downloads and presume throttle. Disable using the override variable `enable_resolution_assert: False`", "Resolution assert is disabled. Use at your own risk!" ), enable_resolution_assert, -1 ) }',
|
||||
"resolution_readable": '{ %concat( %string( width ), %string( "x" ), %string( height ) ) }',
|
||||
"s01_name": "",
|
||||
"s01_url": "",
|
||||
"season_directory_name": '{ %concat( %string( "Season " ), %string( season_number_padded ) ) }',
|
||||
"season_number": '{ %elif( %season_ordering_( "upload-year" ), upload_year, %season_ordering_( "upload-year-month" ), %concat( upload_year, upload_month_padded ), %season_ordering_( "release-year" ), release_year, %season_ordering_( "release-year-month" ), %concat( release_year, release_month_padded ), %throw( \'tv_show_by_date_season_ordering must be one of the following: "upload-year", "upload-year-month", "release-year", "release-year-month"\' ) ) }',
|
||||
"season_number_padded": "{ season_number }",
|
||||
"season_poster_file_name": '{ %concat( %string( season_directory_name_sanitized ), %string( "/Season" ), %string( season_number_padded ), %string( ".jpg" ) ) }',
|
||||
"subscription_array": "{ %from_json( '[\"https://www.youtube.com/@JakeTrains\"]' ) }",
|
||||
"subscription_indent_1": "Kids",
|
||||
"subscription_indent_2": "TV-Y",
|
||||
"subscription_value": "https://www.youtube.com/@JakeTrains",
|
||||
"subscription_value_1": "https://www.youtube.com/@JakeTrains",
|
||||
"thumbnail_file_name": '{ %concat( %string( episode_file_path ), %string( "-thumb.jpg" ) ) }',
|
||||
"tv_show_by_date_episode_ordering": "upload-month-day",
|
||||
"tv_show_by_date_ordering_pair_validation_": '{ %assert_then( %or( %ordering_pair_eq( "upload-year", "upload-month-day" ), %ordering_pair_eq( "upload-year", "upload-month-day-reversed" ), %ordering_pair_eq( "upload-year", "download-index" ), %ordering_pair_eq( "upload-year-month", "upload-day" ), %ordering_pair_eq( "release-year", "release-month-day" ), %ordering_pair_eq( "release-year", "release-month-day-reversed" ), %ordering_pair_eq( "release-year", "download-index" ), %ordering_pair_eq( "release-year-month", "release-day" ) ), episode_number_and_padded_, "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." ) }',
|
||||
"tv_show_by_date_season_ordering": "upload-year",
|
||||
"tv_show_content_rating": "{ subscription_indent_2 }",
|
||||
"tv_show_content_rating_default": "TV-14",
|
||||
"tv_show_date_range_type": '{ %if( %contains( tv_show_by_date_season_ordering, "release" ), "release_date", "upload_date" ) }',
|
||||
"tv_show_directory": output_directory,
|
||||
"tv_show_fanart_file_name": "fanart.jpg",
|
||||
"tv_show_genre": "{ subscription_indent_1 }",
|
||||
"tv_show_genre_default": "ytdl-sub",
|
||||
"tv_show_name": "{ subscription_name }",
|
||||
"tv_show_poster_file_name": "poster.jpg",
|
||||
"url": "{ subscription_value }",
|
||||
"url10": "",
|
||||
"url100": "",
|
||||
"url11": "",
|
||||
"url12": "",
|
||||
"url13": "",
|
||||
"url14": "",
|
||||
"url15": "",
|
||||
"url16": "",
|
||||
"url17": "",
|
||||
"url18": "",
|
||||
"url19": "",
|
||||
"url2": "",
|
||||
"url20": "",
|
||||
"url21": "",
|
||||
"url22": "",
|
||||
"url23": "",
|
||||
"url24": "",
|
||||
"url25": "",
|
||||
"url26": "",
|
||||
"url27": "",
|
||||
"url28": "",
|
||||
"url29": "",
|
||||
"url3": "",
|
||||
"url30": "",
|
||||
"url31": "",
|
||||
"url32": "",
|
||||
"url33": "",
|
||||
"url34": "",
|
||||
"url35": "",
|
||||
"url36": "",
|
||||
"url37": "",
|
||||
"url38": "",
|
||||
"url39": "",
|
||||
"url4": "",
|
||||
"url40": "",
|
||||
"url41": "",
|
||||
"url42": "",
|
||||
"url43": "",
|
||||
"url44": "",
|
||||
"url45": "",
|
||||
"url46": "",
|
||||
"url47": "",
|
||||
"url48": "",
|
||||
"url49": "",
|
||||
"url5": "",
|
||||
"url50": "",
|
||||
"url51": "",
|
||||
"url52": "",
|
||||
"url53": "",
|
||||
"url54": "",
|
||||
"url55": "",
|
||||
"url56": "",
|
||||
"url57": "",
|
||||
"url58": "",
|
||||
"url59": "",
|
||||
"url6": "",
|
||||
"url60": "",
|
||||
"url61": "",
|
||||
"url62": "",
|
||||
"url63": "",
|
||||
"url64": "",
|
||||
"url65": "",
|
||||
"url66": "",
|
||||
"url67": "",
|
||||
"url68": "",
|
||||
"url69": "",
|
||||
"url7": "",
|
||||
"url70": "",
|
||||
"url71": "",
|
||||
"url72": "",
|
||||
"url73": "",
|
||||
"url74": "",
|
||||
"url75": "",
|
||||
"url76": "",
|
||||
"url77": "",
|
||||
"url78": "",
|
||||
"url79": "",
|
||||
"url8": "",
|
||||
"url80": "",
|
||||
"url81": "",
|
||||
"url82": "",
|
||||
"url83": "",
|
||||
"url84": "",
|
||||
"url85": "",
|
||||
"url86": "",
|
||||
"url87": "",
|
||||
"url88": "",
|
||||
"url89": "",
|
||||
"url9": "",
|
||||
"url90": "",
|
||||
"url91": "",
|
||||
"url92": "",
|
||||
"url93": "",
|
||||
"url94": "",
|
||||
"url95": "",
|
||||
"url96": "",
|
||||
"url97": "",
|
||||
"url98": "",
|
||||
"url99": "",
|
||||
"urls": "{ subscription_array }",
|
||||
},
|
||||
"throttle_protection": {
|
||||
"enable": True,
|
||||
"sleep_per_download_s": {"max": "28.4", "min": "13.8"},
|
||||
"sleep_per_request_s": {"max": "0.75", "min": "0.0"},
|
||||
"sleep_per_subscription_s": {"max": "26.1", "min": "16.3"},
|
||||
},
|
||||
"video_tags": {
|
||||
"contentRating": "{episode_content_rating}",
|
||||
"date": "{episode_date_standardized}",
|
||||
"episode_id": "{episode_number}",
|
||||
"genre": "{tv_show_genre}",
|
||||
"show": "{tv_show_name}",
|
||||
"synopsis": "{episode_plot}",
|
||||
"title": "{episode_title}",
|
||||
"year": "{episode_year}",
|
||||
},
|
||||
}
|
||||
out = yaml.safe_load(capsys.readouterr().out)
|
||||
compare_resolved_yaml(
|
||||
out=out,
|
||||
output_directory=output_directory,
|
||||
subscription_name="NOVA PBS",
|
||||
preset_type="tv_show",
|
||||
resolution_level=ResolutionLevel.level_number(resolution_arg=inspect_level),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
|
@ -10,12 +11,13 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
|||
from ytdl_sub.utils.file_path import FilePathTruncater
|
||||
|
||||
|
||||
def _ensure_resolved_yaml(
|
||||
sub: Subscription, output_directory: str, preset_type: str, resolution_level: int
|
||||
def compare_resolved_yaml(
|
||||
out: Dict,
|
||||
output_directory: str,
|
||||
subscription_name: str,
|
||||
preset_type: str,
|
||||
resolution_level: int,
|
||||
) -> None:
|
||||
output_yaml = sub.resolved_yaml(resolution_level=resolution_level)
|
||||
out = yaml.safe_load(output_yaml)
|
||||
|
||||
expected_out_filename = (
|
||||
f"{preset_type}/inspect_sub_{ResolutionLevel.name_of(resolution_level)}.json"
|
||||
)
|
||||
|
|
@ -24,7 +26,7 @@ def _ensure_resolved_yaml(
|
|||
if resolution_level > ResolutionLevel.ORIGINAL:
|
||||
output_path = Path(output_directory)
|
||||
if "tv_show_directory" in expected_out["overrides"]:
|
||||
output_path = output_path / sub.name
|
||||
output_path = output_path / subscription_name
|
||||
|
||||
expected_out["output_options"]["output_directory"] = FilePathTruncater.to_native_filepath(
|
||||
str(output_path)
|
||||
|
|
@ -40,6 +42,21 @@ def _ensure_resolved_yaml(
|
|||
assert out == expected_out
|
||||
|
||||
|
||||
def _ensure_resolved_yaml(
|
||||
sub: Subscription, output_directory: str, preset_type: str, resolution_level: int
|
||||
) -> None:
|
||||
output_yaml = sub.resolved_yaml(resolution_level=resolution_level)
|
||||
out = yaml.safe_load(output_yaml)
|
||||
|
||||
compare_resolved_yaml(
|
||||
out=out,
|
||||
output_directory=output_directory,
|
||||
subscription_name=sub.name,
|
||||
preset_type=preset_type,
|
||||
resolution_level=resolution_level,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("resolution_level", ResolutionLevel.all())
|
||||
class TestResolution:
|
||||
def test_resolution_tv_show(
|
||||
|
|
|
|||
Loading…
Reference in a new issue