[BUGFIX] Actually fix subscription_name with periods in it (#861)

Prior PR did not actually work - this actually fixes the bug (https://github.com/jmbannon/ytdl-sub/issues/844) where subscription names would drop periods from them, i.e. Mr. Beast would have the name  Beast.

POTENTIAL BREAKING CHANGE
If you have a subscription with a period in its name prior to this fix, this change will make it so your download archive is not found since it uses the subscription name in the download archive file path. To fix, simply change the download archive JSON's name to have the actual subscription name, and not the dropped-period one.
This commit is contained in:
Jesse Bannon 2023-12-29 15:41:33 -08:00 committed by GitHub
parent f2d55fdb23
commit 735da8b647
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 110 additions and 97 deletions

View file

@ -7,8 +7,8 @@ import mergedeep
from ytdl_sub.entries.entry import Entry
from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.variables.override_variables import SUBSCRIPTION_NAME
from ytdl_sub.entries.variables.override_variables import OverrideHelpers
from ytdl_sub.entries.variables.override_variables import OverrideVariables
from ytdl_sub.script.parser import parse
from ytdl_sub.script.script import Script
from ytdl_sub.script.utils.exceptions import ScriptVariableNotResolved
@ -124,14 +124,20 @@ class Overrides(DictFormatterValidator, Scriptable):
initial_variables,
self.dict_with_format_strings,
unresolved_variables if unresolved_variables else {},
{SUBSCRIPTION_NAME: self.subscription_name},
)
return ScriptUtils.add_sanitized_variables(initial_variables)
def initialize_script(self, unresolved_variables: Set[str]) -> "Overrides":
def initialize_script(
self, subscription_name: str, unresolved_variables: Set[str]
) -> "Overrides":
"""
Initialize the override script with override variables + any unresolved variables
"""
self.script.add(
ScriptUtils.add_sanitized_variables(
{OverrideVariables.subscription_name(): subscription_name}
)
)
self.script.add(
self.initial_variables(
unresolved_variables={
@ -144,15 +150,6 @@ class Overrides(DictFormatterValidator, Scriptable):
self.update_script()
return self
@property
def subscription_name(self) -> str:
"""
Returns
-------
Name of the subscription
"""
return self._root_name
def apply_formatter(
self,
formatter: StringFormatterValidator,

View file

@ -198,7 +198,9 @@ class Preset(_PresetShell):
downloader_options=self.downloader_options,
output_options=self.output_options,
plugins=self.plugins,
).initialize_overrides(overrides=self.overrides).ensure_proper_usage()
).initialize_overrides(
subscription_name=self.name, overrides=self.overrides
).ensure_proper_usage()
@property
def name(self) -> str:

View file

@ -14,6 +14,7 @@ from ytdl_sub.config.preset_options import OutputOptions
from ytdl_sub.config.validators.options import OptionsValidator
from ytdl_sub.downloaders.url.validators import MultiUrlValidator
from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS
from ytdl_sub.entries.variables.override_variables import OverrideVariables
from ytdl_sub.script.script import Script
from ytdl_sub.validators.string_formatter_validators import validate_formatters
@ -66,7 +67,7 @@ def _get_added_and_modified_variables(
def _override_variables(overrides: Overrides) -> Set[str]:
return set(list(overrides.initial_variables().keys()))
return set(list(overrides.initial_variables().keys())) | {OverrideVariables.subscription_name()}
def _entry_variables() -> Set[str]:
@ -88,7 +89,9 @@ class VariableValidation:
self.resolved_variables: Set[str] = set()
self.unresolved_variables: Set[str] = set()
def initialize_overrides(self, overrides: Overrides) -> "VariableValidation":
def initialize_overrides(
self, subscription_name: str, overrides: Overrides
) -> "VariableValidation":
"""
Do some gymnastics to initialize the Overrides script.
"""
@ -127,7 +130,9 @@ class VariableValidation:
# Initialize overrides with unresolved variables + modified variables to throw an error.
# For modified variables, this is to prevent a resolve(update=True) to setting any
# dependencies until it has been explicitly added
overrides = overrides.initialize_script(unresolved_variables=self.unresolved_variables)
overrides = overrides.initialize_script(
subscription_name=subscription_name, unresolved_variables=self.unresolved_variables
)
# copy the script and mock entry variables
self.script = copy.deepcopy(overrides.script).add(_add_dummy_variables(entry_variables))

View file

@ -3,9 +3,7 @@ from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS
from ytdl_sub.script.functions import Functions
from ytdl_sub.script.utils.name_validation import is_valid_name
SUBSCRIPTION_NAME = "subscription_name"
SUBSCRIPTION_VALUE = "subscription_value"
SUBSCRIPTION_MAP = "subscription_map"
# TODO: use this
SUBSCRIPTION_ARRAY = "subscription_array"
@ -15,7 +13,7 @@ class OverrideVariables:
"""
Name of the subscription
"""
return SUBSCRIPTION_NAME
return "subscription_name"
@staticmethod
def subscription_value() -> str:
@ -28,7 +26,7 @@ class OverrideVariables:
``subscription_value`` gets set to ``https://...``.
"""
return SUBSCRIPTION_VALUE
return "subscription_value"
@staticmethod
def subscription_indent_i(index: int) -> str:
@ -90,7 +88,7 @@ class OverrideVariables:
]
}
"""
return SUBSCRIPTION_MAP
return "subscription_map"
class OverrideHelpers:

View file

@ -9,9 +9,6 @@ from typing import final
from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.config.overrides import Overrides
from ytdl_sub.entries.variables.override_variables import SUBSCRIPTION_MAP
from ytdl_sub.entries.variables.override_variables import SUBSCRIPTION_NAME
from ytdl_sub.entries.variables.override_variables import SUBSCRIPTION_VALUE
from ytdl_sub.entries.variables.override_variables import OverrideVariables
from ytdl_sub.utils.script import ScriptUtils
from ytdl_sub.validators.string_formatter_validators import DictFormatterValidator
@ -85,7 +82,6 @@ class SubscriptionPresetDictValidator(NamedSubscriptionValidator, DictValidator)
output_dict["overrides"] = dict(
output_dict.get("overrides", {}),
**self._indent_overrides_dict(),
**{SUBSCRIPTION_NAME: self.subscription_name},
)
return {self.subscription_name: output_dict}
@ -114,7 +110,7 @@ class SubscriptionLeafValidator(NamedSubscriptionValidator, ABC):
f"used as a subscription name"
)
self._overrides_to_add: Dict[str, str] = {SUBSCRIPTION_NAME: self.subscription_name}
self._overrides_to_add: Dict[str, str] = {}
@final
def subscription_dicts(self, global_presets_to_apply: List[str]) -> Dict[str, Dict]:
@ -147,7 +143,7 @@ class SubscriptionValueValidator(SubscriptionLeafValidator, StringValidator):
presets=presets,
indent_overrides=indent_overrides,
)
self._overrides_to_add[SUBSCRIPTION_VALUE] = self.value
self._overrides_to_add[OverrideVariables.subscription_value()] = self.value
class SubscriptionListValuesValidator(SubscriptionLeafValidator, StringListValidator):
@ -172,7 +168,7 @@ class SubscriptionListValuesValidator(SubscriptionLeafValidator, StringListValid
for idx, list_value in enumerate(self.list):
# Write the first list value into subscription_value as well
if idx == 0:
self._overrides_to_add[SUBSCRIPTION_VALUE] = list_value.value
self._overrides_to_add[OverrideVariables.subscription_value()] = list_value.value
self._overrides_to_add[
OverrideVariables.subscription_value_i(index=idx)
@ -219,7 +215,9 @@ class SubscriptionMapValidator(SubscriptionLeafValidator, LiteralDictValidator):
presets=presets,
indent_overrides=indent_overrides,
)
self._overrides_to_add = {SUBSCRIPTION_MAP: ScriptUtils.to_script(self.dict)}
self._overrides_to_add[OverrideVariables.subscription_map()] = ScriptUtils.to_script(
self.dict
)
class SubscriptionValidator(SubscriptionOutput):

View file

@ -225,9 +225,9 @@ def test_subscription_file_preset_applies(config_file: ConfigFile, preset_with_f
"key-4": "test_preset",
}
overrides = preset_sub.overrides.dict_with_format_strings
overrides = preset_sub.overrides.script
# preset overrides take precedence over __preset__
assert overrides.get("current_override") == "test_preset"
assert overrides.get("current_override").native == "test_preset"
def test_subscription_list(
@ -238,13 +238,15 @@ def test_subscription_list(
subs = Subscription.from_file_path(config=config_file, subscription_path="mocked")
assert len(subs) == 3
sub_2_1 = [sub for sub in subs if sub.name == "test_2_1"][0].overrides.dict_with_format_strings
sub_2_1 = [sub for sub in subs if sub.name == "test_2_1"][0].overrides.script
assert sub_2_1.get("subscription_name") == "test_2_1"
assert sub_2_1.get("subscription_value") == "is_2_1_overwritten"
assert sub_2_1.get("subscription_value_1") == "is_2_1_overwritten"
assert sub_2_1.get("subscription_value_2") == "is_2_1_list_2"
assert sub_2_1.get("current_override") == "__preset__" # ensure __preset__ takes precedence
assert sub_2_1.get("subscription_name").native == "test_2_1"
assert sub_2_1.get("subscription_value").native == "is_2_1_overwritten"
assert sub_2_1.get("subscription_value_1").native == "is_2_1_overwritten"
assert sub_2_1.get("subscription_value_2").native == "is_2_1_list_2"
assert (
sub_2_1.get("current_override").native == "__preset__"
) # ensure __preset__ takes precedence
def test_subscription_overrides_tilda(
@ -255,10 +257,10 @@ def test_subscription_overrides_tilda(
subs = Subscription.from_file_path(config=config_file, subscription_path="mocked")
assert len(subs) == 3
sub_2_1 = [sub for sub in subs if sub.name == "test_2_1"][0].overrides.dict_with_format_strings
sub_2_1 = [sub for sub in subs if sub.name == "test_2_1"][0].overrides.script
assert sub_2_1.get("subscription_name") == "test_2_1"
assert sub_2_1.get("current_override") == "test_2_1" # tilda sub takes precedence
assert sub_2_1.get("subscription_name").native == "test_2_1"
assert sub_2_1.get("current_override").native == "test_2_1" # tilda sub takes precedence
def test_subscription_overrides_map(
@ -291,7 +293,7 @@ def test_subscription_with_period_in_name(
assert len(subs) == 2
assert subs[1].name == "Mr. Beast"
assert subs[1].overrides.dict_with_format_strings["subscription_name"] == "Mr. Beast"
assert subs[1].overrides.script.get("subscription_name").native == "Mr. Beast"
def test_subscription_file_value_applies_from_config_and_nested_and_indent_variables(
@ -304,26 +306,28 @@ def test_subscription_file_value_applies_from_config_and_nested_and_indent_varia
subs = Subscription.from_file_path(config=config_file, subscription_path="mocked")
assert len(subs) == 4
sub_test_value = [sub for sub in subs if sub.name == "test_value"][
0
].overrides.dict_with_format_strings
sub_1 = [sub for sub in subs if sub.name == "test_1"][0].overrides.dict_with_format_strings
sub_2_1 = [sub for sub in subs if sub.name == "test_2_1"][0].overrides.dict_with_format_strings
sub_test_value = [sub for sub in subs if sub.name == "test_value"][0].overrides.script
sub_1 = [sub for sub in subs if sub.name == "test_1"][0].overrides.script
sub_2_1 = [sub for sub in subs if sub.name == "test_2_1"][0].overrides.script
assert sub_test_value.get("subscription_indent_1") == "original_1"
assert sub_test_value.get("subscription_indent_2") == "original_2"
assert sub_test_value.get("subscription_indent_1").native == "original_1"
assert sub_test_value.get("subscription_indent_2").native == "original_2"
assert sub_1.get("subscription_name") == "test_1"
assert sub_1.get("subscription_value") == "is_1_overwritten"
assert sub_1.get("subscription_indent_1") == "INDENT_1"
assert sub_1.get("subscription_indent_2") == "INDENT_2"
assert sub_1.get("current_override") == "__preset__" # ensure __preset__ takes precedence
assert sub_1.get("subscription_name").native == "test_1"
assert sub_1.get("subscription_value").native == "is_1_overwritten"
assert sub_1.get("subscription_indent_1").native == "INDENT_1"
assert sub_1.get("subscription_indent_2").native == "INDENT_2"
assert (
sub_1.get("current_override").native == "__preset__"
) # ensure __preset__ takes precedence
assert sub_2_1.get("subscription_name") == "test_2_1"
assert sub_2_1.get("subscription_value") == "is_2_1_overwritten"
assert sub_2_1.get("subscription_indent_1") == "INDENT_1"
assert sub_2_1.get("subscription_indent_2") == "original_2"
assert sub_2_1.get("current_override") == "__preset__" # ensure __preset__ takes precedence
assert sub_2_1.get("subscription_name").native == "test_2_1"
assert sub_2_1.get("subscription_value").native == "is_2_1_overwritten"
assert sub_2_1.get("subscription_indent_1").native == "INDENT_1"
assert sub_2_1.get("subscription_indent_2").native == "original_2"
assert (
sub_2_1.get("current_override").native == "__preset__"
) # ensure __preset__ takes precedence
@pytest.mark.parametrize("all_same_line", [True, False])
@ -343,28 +347,28 @@ def test_subscription_file_value_applies_from_config_and_nested_and_indent_varia
subs = Subscription.from_file_path(config=config_file, subscription_path="mocked")
assert len(subs) == 4
sub_test_value = [sub for sub in subs if sub.name == "test_value"][
0
].overrides.dict_with_format_strings
sub_1 = [sub for sub in subs if sub.name == "test_1"][0].overrides.dict_with_format_strings
sub_2_1 = [sub for sub in subs if sub.name == "test_2_1"][0].overrides.dict_with_format_strings
sub_test_value = [sub for sub in subs if sub.name == "test_value"][0].overrides.script
sub_1 = [sub for sub in subs if sub.name == "test_1"][0].overrides.script
sub_2_1 = [sub for sub in subs if sub.name == "test_2_1"][0].overrides.script
assert sub_test_value.get("subscription_indent_1") == "original_1"
assert sub_test_value.get("subscription_indent_2") == "original_2"
assert sub_test_value.get("subscription_indent_1").native == "original_1"
assert sub_test_value.get("subscription_indent_2").native == "original_2"
assert sub_1.get("subscription_name") == "test_1"
assert sub_1.get("subscription_value") == "is_1_overwritten"
assert sub_1.get("subscription_indent_1") == "INDENT_1"
assert sub_1.get("subscription_indent_2") == "INDENT_2"
assert sub_1.get("subscription_indent_3") == "INDENT_3"
assert sub_1.get("current_override") == "__preset__" # ensure __preset__ takes precedence
assert sub_1.get("subscription_name").native == "test_1"
assert sub_1.get("subscription_value").native == "is_1_overwritten"
assert sub_1.get("subscription_indent_1").native == "INDENT_1"
assert sub_1.get("subscription_indent_2").native == "INDENT_2"
assert sub_1.get("subscription_indent_3").native == "INDENT_3"
# ensure __preset__ takes precedence
assert sub_1.get("current_override").native == "__preset__"
assert sub_2_1.get("subscription_name") == "test_2_1"
assert sub_2_1.get("subscription_value") == "is_2_1_overwritten"
assert sub_2_1.get("subscription_indent_1") == "INDENT_1"
assert sub_2_1.get("subscription_indent_2") == "original_2"
assert sub_2_1.get("current_override") == "__preset__" # ensure __preset__ takes precedence
assert "subscription_indent_3" not in sub_2_1
assert sub_2_1.get("subscription_name").native == "test_2_1"
assert sub_2_1.get("subscription_value").native == "is_2_1_overwritten"
assert sub_2_1.get("subscription_indent_1").native == "INDENT_1"
assert sub_2_1.get("subscription_indent_2").native == "original_2"
# ensure __preset__ takes precedence
assert sub_2_1.get("current_override").native == "__preset__"
assert "subscription_indent_3" not in sub_2_1.variable_names
def test_subscription_file_value_applies_from_config_and_nested_and_indent_variables_same_line_old_format_errors(
@ -414,12 +418,15 @@ def test_tv_show_subscriptions(config_file: ConfigFile, tv_show_subscriptions_pa
assert len(subs) == 7
assert subs[3].name == "Jake Trains"
jake_train_overrides = subs[3].overrides.dict_with_format_strings
jake_train_overrides = subs[3].overrides.script
assert jake_train_overrides["subscription_name"] == "Jake Trains"
assert jake_train_overrides["subscription_value"] == "https://www.youtube.com/@JakeTrains"
assert jake_train_overrides["subscription_indent_1"] == "Kids"
assert jake_train_overrides["subscription_indent_2"] == "TV-Y"
assert jake_train_overrides.get("subscription_name").native == "Jake Trains"
assert (
jake_train_overrides.get("subscription_value").native
== "https://www.youtube.com/@JakeTrains"
)
assert jake_train_overrides.get("subscription_indent_1").native == "Kids"
assert jake_train_overrides.get("subscription_indent_2").native == "TV-Y"
def test_advanced_tv_show_subscriptions(
@ -431,17 +438,20 @@ def test_advanced_tv_show_subscriptions(
assert len(subs) == 9
assert subs[3].name == "Jake Trains"
jake_train_overrides = subs[3].overrides.dict_with_format_strings
jake_train_overrides = subs[3].overrides.script
assert jake_train_overrides["subscription_name"] == "Jake Trains"
assert jake_train_overrides["subscription_value"] == "https://www.youtube.com/@JakeTrains"
assert jake_train_overrides["subscription_indent_1"] == "Kids"
assert jake_train_overrides["subscription_indent_2"] == "TV-Y"
assert jake_train_overrides.get("subscription_name").native == "Jake Trains"
assert (
jake_train_overrides.get("subscription_value").native
== "https://www.youtube.com/@JakeTrains"
)
assert jake_train_overrides.get("subscription_indent_1").native == "Kids"
assert jake_train_overrides.get("subscription_indent_2").native == "TV-Y"
assert subs[5].name == "Gardening with Ciscoe"
overrides = subs[5].overrides
assert overrides.apply_formatter(overrides.dict["subscription_name"]) == "Gardening with Ciscoe"
assert overrides.script.get("subscription_name").native == "Gardening with Ciscoe"
assert (
overrides.apply_formatter(overrides.dict["url"])
== "https://www.youtube.com/@gardeningwithciscoe4430"
@ -459,11 +469,14 @@ def test_music_subscriptions(default_config: ConfigFile, music_subscriptions_pat
assert len(subs) == 14
assert subs[2].name == "Stan Getz"
monk = subs[2].overrides.dict_with_format_strings
monk = subs[2].overrides.script
assert monk["subscription_name"] == "Stan Getz"
assert monk["subscription_value"] == "https://www.youtube.com/@stangetzofficial/releases"
assert monk["subscription_indent_1"] == "Jazz"
assert monk.get("subscription_name").native == "Stan Getz"
assert (
monk.get("subscription_value").native
== "https://www.youtube.com/@stangetzofficial/releases"
)
assert monk.get("subscription_indent_1").native == "Jazz"
def test_music_video_subscriptions(default_config: ConfigFile, music_video_subscription_path: Path):
@ -473,14 +486,14 @@ def test_music_video_subscriptions(default_config: ConfigFile, music_video_subsc
assert len(subs) == 3
assert subs[1].name == "Michael Jackson"
monk = subs[1].overrides.dict_with_format_strings
monk = subs[1].overrides.script
assert monk["subscription_name"] == "Michael Jackson"
assert monk.get("subscription_name").native == "Michael Jackson"
assert (
monk["subscription_value"]
monk.get("subscription_value").native
== "https://www.youtube.com/playlist?list=OLAK5uy_mnY03zP6abNWH929q2XhGzWD_2uKJ_n8E"
)
assert monk["subscription_indent_1"] == "Pop"
assert monk.get("subscription_indent_1").native == "Pop"
def test_default_docker_config_and_subscriptions():