This commit is contained in:
Jesse Bannon 2023-10-02 15:47:20 -07:00
parent f9665ff066
commit e2e309b3ef
4 changed files with 98 additions and 28 deletions

View file

@ -299,8 +299,66 @@ custom variables: ``{output_directory}``, ``{playlist_name}``, and ``{url}``. Th
the `parent preset`_ to ``playlist_preset_ex``, and must define the variables ``{playlist_name}`` the `parent preset`_ to ``playlist_preset_ex``, and must define the variables ``{playlist_name}``
and ``{url}`` since the preset did not. and ``{url}`` since the preset did not.
.. _beautifying subscriptions:
Beautifying Subscriptions
^^^^^^^^^^^^^^^^^^^^^^^^^
Subscriptions support using presets as keys, and using keys to set override variables as values.
For example:
.. code-block:: yaml
:caption: subscription.yaml
tv_show:
only_recent:
[News]:
"Breaking News": "https://www.youtube.com/@SomeBreakingNews"
[Tech]:
"Two Minute Papers": "https://www.youtube.com/@TwoMinutePapers"
Will create two subscriptions named "Breaking News" and "Two Minute Papers", equivalent to:
.. code-block:: yaml
"Breaking News":
preset:
- "tv_show"
- "only_recent"
overrides:
subscription_indent_1: "News"
subscription_name: "Breaking News"
subscription_value: "https://www.youtube.com/@SomeBreakingNews"
"Two Minute Papers":
preset:
- "tv_show"
overrides:
subscription_indent_1: "Tech"
subscription_name: "Two Minute Papers"
subscription_value: "https://www.youtube.com/@TwoMinutePapers"
You can provide as many parent presets in the form of keys, and subscription indents as ``[keys]``.
This can drastically simplify subscription definitions by setting things like so in your
parent preset:
.. code-block:: yaml
presets:
tv_show_name:
overrides:
tv_show_name: "{subscription_name}"
url: "{subscription_value}"
genre: "{subscription_indent_1}"
.. _subscription value:
File Preset File Preset
^^^^^^^^^^^ ^^^^^^^^^^^
NOTE: This is deprecated in favor of using the method in :ref:`beautifying subscriptions`.
You can apply a preset to all subscriptions in the ``subscription.yaml`` file You can apply a preset to all subscriptions in the ``subscription.yaml`` file
by using the file-wide ``__preset__``: by using the file-wide ``__preset__``:
@ -318,10 +376,11 @@ by using the file-wide ``__preset__``:
This ``subscription.yaml`` is equivalent to the one above it because all This ``subscription.yaml`` is equivalent to the one above it because all
subscriptions automatically set ``__preset__`` as a `parent preset`_. subscriptions automatically set ``__preset__`` as a `parent preset`_.
.. _subscription value:
Subscription Value Subscription Value
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
NOTE: This is deprecated in favor of using the method in :ref:`beautifying subscriptions`.
With a clever config and use of ``__preset__``, your subscriptions can typically boil With a clever config and use of ``__preset__``, your subscriptions can typically boil
down to a name and url. You can set ``__value__`` to the name of an override variable, down to a name and url. You can set ``__value__`` to the name of an override variable,
and use the override variable ``subscription_name`` to achieve one-liner subscriptions. and use the override variable ``subscription_name`` to achieve one-liner subscriptions.

View file

@ -9,12 +9,15 @@ 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.subscriptions.subscription_validators import SubscriptionValidator from ytdl_sub.subscriptions.subscription_validators import SubscriptionValidator
from ytdl_sub.utils.exceptions import ValidationException from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.logger import Logger
from ytdl_sub.utils.yaml import load_yaml from ytdl_sub.utils.yaml import load_yaml
from ytdl_sub.validators.validators import LiteralDictValidator from ytdl_sub.validators.validators import LiteralDictValidator
FILE_PRESET_APPLY_KEY = "__preset__" FILE_PRESET_APPLY_KEY = "__preset__"
FILE_SUBSCRIPTION_VALUE_KEY = "__value__" FILE_SUBSCRIPTION_VALUE_KEY = "__value__"
logger = Logger.get("subscription")
class Subscription(SubscriptionDownload): class Subscription(SubscriptionDownload):
@classmethod @classmethod
@ -70,15 +73,23 @@ class Subscription(SubscriptionDownload):
def _maybe_get_subscription_value( def _maybe_get_subscription_value(
cls, config: ConfigFile, subscription_dict: Dict cls, config: ConfigFile, subscription_dict: Dict
) -> Optional[str]: ) -> Optional[str]:
subscription_value_key: Optional[str] = config.config_options.subscription_value
if FILE_SUBSCRIPTION_VALUE_KEY in subscription_dict: if FILE_SUBSCRIPTION_VALUE_KEY in subscription_dict:
if not isinstance(subscription_dict[FILE_SUBSCRIPTION_VALUE_KEY], str): if not isinstance(subscription_dict[FILE_SUBSCRIPTION_VALUE_KEY], str):
raise ValidationException( raise ValidationException(
f"Using {FILE_SUBSCRIPTION_VALUE_KEY} in a subscription" f"Using {FILE_SUBSCRIPTION_VALUE_KEY} in a subscription"
f"must be a string that corresponds to an override variable" f"must be a string that corresponds to an override variable"
) )
return subscription_dict[FILE_SUBSCRIPTION_VALUE_KEY]
return config.config_options.subscription_value # can be None subscription_value_key = subscription_dict[FILE_SUBSCRIPTION_VALUE_KEY]
if subscription_value_key is not None:
logger.warning(
"Using %s in a subscription will eventually be deprecated in favor of writing "
"to the override variable `subscription_value`. Please update by Dec 2023.",
FILE_SUBSCRIPTION_VALUE_KEY,
)
return subscription_value_key
@classmethod @classmethod
def from_file_path(cls, config: ConfigFile, subscription_path: str) -> List["Subscription"]: def from_file_path(cls, config: ConfigFile, subscription_path: str) -> List["Subscription"]:

View file

@ -27,6 +27,15 @@ def subscription_indent_variable_name(index: int) -> str:
return f"subscription_indent_{index + 1}" return f"subscription_indent_{index + 1}"
def subscription_value_variable_name() -> str:
"""
Returns
-------
The override variable name containing the subscription value if present
"""
return "subscription_value"
def maybe_indent_override_value(value: str) -> Optional[str]: def maybe_indent_override_value(value: str) -> Optional[str]:
""" """
Returns Returns
@ -117,7 +126,11 @@ class SubscriptionValueValidator(SubscriptionOutput, StringValidator):
self._leaf_name: { self._leaf_name: {
"preset": self._presets, "preset": self._presets,
"overrides": dict( "overrides": dict(
{self._subscription_value: self.value}, **self._indent_overrides_dict() {
self._subscription_value: self.value,
"subscription_value": self.value,
},
**self._indent_overrides_dict(),
), ),
} }
} }

View file

@ -138,15 +138,12 @@ def test_subscription_file_value_applies(
# Test __value__ worked correctly # Test __value__ worked correctly
value_sub = subs[1] value_sub = subs[1]
overrides = value_sub.overrides.dict_with_format_strings
assert value_sub.name == "test_value" assert value_sub.name == "test_value"
assert (
value_sub.overrides.dict_with_format_strings.get("test_file_subscription_value") assert overrides.get("test_file_subscription_value") == "is_overwritten"
== "is_overwritten" assert overrides.get("test_file_subscription_value")
) assert overrides.get("subscription_value") == "is_overwritten"
assert (
value_sub.overrides.dict_with_format_strings.get("test_config_subscription_value")
== "original"
)
def test_subscription_file_value_applies_sub_file_takes_precedence( def test_subscription_file_value_applies_sub_file_takes_precedence(
@ -161,15 +158,10 @@ def test_subscription_file_value_applies_sub_file_takes_precedence(
# Test __value__ worked correctly # Test __value__ worked correctly
value_sub = subs[1] value_sub = subs[1]
overrides = value_sub.overrides.dict_with_format_strings
assert value_sub.name == "test_value" assert value_sub.name == "test_value"
assert ( assert overrides.get("test_file_subscription_value") == "is_overwritten"
value_sub.overrides.dict_with_format_strings.get("test_file_subscription_value") assert overrides.get("test_config_subscription_value") == "original"
== "is_overwritten"
)
assert (
value_sub.overrides.dict_with_format_strings.get("test_config_subscription_value")
== "original"
)
def test_subscription_file_value_applies_from_config( def test_subscription_file_value_applies_from_config(
@ -183,15 +175,10 @@ def test_subscription_file_value_applies_from_config(
# Test __value__ worked correctly from the config # Test __value__ worked correctly from the config
value_sub = subs[1] value_sub = subs[1]
overrides = value_sub.overrides.dict_with_format_strings
assert value_sub.name == "test_value" assert value_sub.name == "test_value"
assert ( assert overrides.get("test_file_subscription_value") == "original"
value_sub.overrides.dict_with_format_strings.get("test_file_subscription_value") assert overrides.get("test_config_subscription_value") == "is_overwritten"
== "original"
)
assert (
value_sub.overrides.dict_with_format_strings.get("test_config_subscription_value")
== "is_overwritten"
)
def test_subscription_file_value_applies_from_config_and_nested( def test_subscription_file_value_applies_from_config_and_nested(