[FEATURE] Add subscription yaml file preset __preset__ and apply to all presets in the file (#292)
This commit is contained in:
parent
4ce3d9e9fb
commit
6125fd0efb
4 changed files with 136 additions and 50 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
import copy
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
|
@ -5,6 +6,9 @@ from ytdl_sub.config.config_file import ConfigFile
|
||||||
from ytdl_sub.config.preset import Preset
|
from ytdl_sub.config.preset import Preset
|
||||||
from ytdl_sub.subscriptions.subscription_download import SubscriptionDownload
|
from ytdl_sub.subscriptions.subscription_download import SubscriptionDownload
|
||||||
from ytdl_sub.utils.yaml import load_yaml
|
from ytdl_sub.utils.yaml import load_yaml
|
||||||
|
from ytdl_sub.validators.validators import LiteralDictValidator
|
||||||
|
|
||||||
|
FILE_PRESET_APPLY_KEY = "__preset__"
|
||||||
|
|
||||||
|
|
||||||
class Subscription(SubscriptionDownload):
|
class Subscription(SubscriptionDownload):
|
||||||
|
|
@ -71,10 +75,40 @@ class Subscription(SubscriptionDownload):
|
||||||
-------
|
-------
|
||||||
List of subscriptions, for each one in the subscription yaml
|
List of subscriptions, for each one in the subscription yaml
|
||||||
"""
|
"""
|
||||||
|
subscriptions: List["Subscription"] = []
|
||||||
subscription_dict = load_yaml(file_path=subscription_path)
|
subscription_dict = load_yaml(file_path=subscription_path)
|
||||||
|
|
||||||
subscriptions: List["Subscription"] = []
|
has_file_preset = FILE_PRESET_APPLY_KEY in subscription_dict
|
||||||
|
|
||||||
|
# If a file preset is present...
|
||||||
|
if has_file_preset:
|
||||||
|
# Validate it (make sure it is a dict)
|
||||||
|
file_preset = LiteralDictValidator(
|
||||||
|
name=f"{subscription_path}.{FILE_PRESET_APPLY_KEY}",
|
||||||
|
value=subscription_dict[FILE_PRESET_APPLY_KEY],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Deep copy the config and add this file preset to its preset list
|
||||||
|
config = copy.deepcopy(config)
|
||||||
|
config.presets.dict[FILE_PRESET_APPLY_KEY] = file_preset.dict
|
||||||
|
|
||||||
for subscription_key, subscription_object in subscription_dict.items():
|
for subscription_key, subscription_object in subscription_dict.items():
|
||||||
|
|
||||||
|
# Skip file preset
|
||||||
|
if subscription_key == FILE_PRESET_APPLY_KEY:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# If it has file_preset, inject it as a parent preset
|
||||||
|
if has_file_preset:
|
||||||
|
parent_preset = subscription_object.get("preset", [])
|
||||||
|
# Preset can be a single string
|
||||||
|
if isinstance(parent_preset, str):
|
||||||
|
parent_preset = [parent_preset]
|
||||||
|
|
||||||
|
# If it's not a string or list, it will fail downstream
|
||||||
|
if isinstance(parent_preset, list):
|
||||||
|
subscription_object["preset"] = parent_preset + [FILE_PRESET_APPLY_KEY]
|
||||||
|
|
||||||
subscriptions.append(
|
subscriptions.append(
|
||||||
cls.from_dict(
|
cls.from_dict(
|
||||||
config=config,
|
config=config,
|
||||||
|
|
|
||||||
53
tests/unit/config/conftest.py
Normal file
53
tests/unit/config/conftest.py
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from ytdl_sub.config.config_file import ConfigFile
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def config_file() -> ConfigFile:
|
||||||
|
return ConfigFile(
|
||||||
|
name="config",
|
||||||
|
value={
|
||||||
|
"configuration": {"working_directory": "."},
|
||||||
|
"presets": {
|
||||||
|
"parent_preset_0": {"nfo_tags": {"tags": {"key-1": "preset_0"}}},
|
||||||
|
"parent_preset_1": {
|
||||||
|
"preset": "parent_preset_0",
|
||||||
|
"nfo_tags": {
|
||||||
|
"nfo_name": "{uid}.nfo",
|
||||||
|
"nfo_root": "root",
|
||||||
|
"tags": {"key-2": "preset_1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"parent_preset_2": {
|
||||||
|
"nfo_tags": {
|
||||||
|
"nfo_name": "{uid}.nfo",
|
||||||
|
"nfo_root": "root",
|
||||||
|
"tags": {"key-2": "preset_2", "key-3": "preset_2"},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parent_preset_3": {"preset": ["parent_preset_1", "parent_preset_2"]},
|
||||||
|
"preset_self_loop": {"preset": "preset_self_loop"},
|
||||||
|
"preset_loop_0": {"preset": "preset_loop_1"},
|
||||||
|
"preset_loop_1": {"preset": "preset_loop_0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def output_options() -> Dict:
|
||||||
|
return {
|
||||||
|
"output_directory": "some dir",
|
||||||
|
"file_name": "{uid}",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def youtube_video() -> Dict:
|
||||||
|
return {
|
||||||
|
"download_strategy": "video",
|
||||||
|
"video_url": "youtube.com/watch?v=123abc",
|
||||||
|
}
|
||||||
|
|
@ -2,61 +2,12 @@ from typing import Dict
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ytdl_sub.config.config_file import ConfigFile
|
|
||||||
from ytdl_sub.config.preset import Preset
|
from ytdl_sub.config.preset import Preset
|
||||||
from ytdl_sub.plugins.nfo_tags import NfoTagsOptions
|
from ytdl_sub.plugins.nfo_tags import NfoTagsOptions
|
||||||
from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException
|
from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException
|
||||||
from ytdl_sub.utils.exceptions import ValidationException
|
from ytdl_sub.utils.exceptions import ValidationException
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def config_file() -> ConfigFile:
|
|
||||||
return ConfigFile(
|
|
||||||
name="config",
|
|
||||||
value={
|
|
||||||
"configuration": {"working_directory": "."},
|
|
||||||
"presets": {
|
|
||||||
"parent_preset_0": {"nfo_tags": {"tags": {"key-1": "preset_0"}}},
|
|
||||||
"parent_preset_1": {
|
|
||||||
"preset": "parent_preset_0",
|
|
||||||
"nfo_tags": {
|
|
||||||
"nfo_name": "{uid}.nfo",
|
|
||||||
"nfo_root": "root",
|
|
||||||
"tags": {"key-2": "preset_1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"parent_preset_2": {
|
|
||||||
"nfo_tags": {
|
|
||||||
"nfo_name": "{uid}.nfo",
|
|
||||||
"nfo_root": "root",
|
|
||||||
"tags": {"key-2": "preset_2", "key-3": "preset_2"},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"parent_preset_3": {"preset": ["parent_preset_1", "parent_preset_2"]},
|
|
||||||
"preset_self_loop": {"preset": "preset_self_loop"},
|
|
||||||
"preset_loop_0": {"preset": "preset_loop_1"},
|
|
||||||
"preset_loop_1": {"preset": "preset_loop_0"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def output_options() -> Dict:
|
|
||||||
return {
|
|
||||||
"output_directory": "some dir",
|
|
||||||
"file_name": "{uid}",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def youtube_video() -> Dict:
|
|
||||||
return {
|
|
||||||
"download_strategy": "video",
|
|
||||||
"video_url": "youtube.com/watch?v=123abc",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class TestPreset:
|
class TestPreset:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"source, download_strategy",
|
"source, download_strategy",
|
||||||
|
|
|
||||||
48
tests/unit/config/test_subscription.py
Normal file
48
tests/unit/config/test_subscription.py
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
from typing import Dict
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from ytdl_sub.config.config_file import ConfigFile
|
||||||
|
from ytdl_sub.plugins.nfo_tags import NfoTagsOptions
|
||||||
|
from ytdl_sub.subscriptions.subscription import Subscription
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def preset_file(youtube_video: Dict, output_options: Dict) -> Dict:
|
||||||
|
return {
|
||||||
|
"__preset__": {
|
||||||
|
"youtube": youtube_video,
|
||||||
|
"output_options": output_options,
|
||||||
|
"nfo_tags": {
|
||||||
|
"tags": {"key-3": "file_preset"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test_preset": {
|
||||||
|
"preset": "parent_preset_3",
|
||||||
|
"nfo_tags": {
|
||||||
|
"tags": {"key-4": "test_preset"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_subscription_file_preset_applies(config_file: ConfigFile, preset_file: Dict):
|
||||||
|
with patch("ytdl_sub.subscriptions.subscription.load_yaml") as mock_load_yaml:
|
||||||
|
mock_load_yaml.return_value = preset_file
|
||||||
|
|
||||||
|
subs = Subscription.from_file_path(config=config_file, subscription_path="mocked")
|
||||||
|
assert len(subs) == 1
|
||||||
|
|
||||||
|
nfo_options: NfoTagsOptions = subs[0].plugins.get(NfoTagsOptions)
|
||||||
|
tags_string_dict = {
|
||||||
|
key: formatter[0].format_string
|
||||||
|
for key, formatter in nfo_options.tags.string_tags.items()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert tags_string_dict == {
|
||||||
|
"key-1": "preset_0",
|
||||||
|
"key-2": "preset_2",
|
||||||
|
"key-3": "file_preset",
|
||||||
|
"key-4": "test_preset",
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue