[BACKEND] Disallow override names conflicting with plugin names (#1399)

Disallow override variable names conflicting with plugin names.

May cause backward incompatible issues from `date_range` being an old override variable name for the `Only Recent` preset. Update this variable name to `only_recent_date_range` to resolve. More info in https://ytdl-sub.readthedocs.io/en/latest/deprecation_notices.html
This commit is contained in:
Jesse Bannon 2025-12-26 15:30:37 -08:00 committed by GitHub
parent 157a0b59c4
commit 0f96d8e24e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 57 additions and 7 deletions

View file

@ -1,6 +1,15 @@
Deprecation Notices
===================
Dec 2025
--------
Override variables names can no longer be plugin names, to avoid the common pitfall of
defining a plugin underneath ``overrides``.
In the past, there was usage of a ``date_range`` override variable in a few example configs
that complimented the ``Only Recent`` preset. This overrride variable usage needs to be
replaced with ``only_recent_date_range``.
Sep 2024
--------

View file

@ -24,6 +24,6 @@ TV Show Only Recent:
# to set only for that subscriptions
"~BBC News":
url: "https://www.youtube.com/@BBCNews" # use url2, url3, ... for multi-url in this form
date_range: "2weeks"
only_recent_date_range: "2weeks"
"Frontline PBS": "https://www.youtube.com/@frontline"
"Whitehouse": "https://www.bitchute.com/channel/zWsYVmCOu4JA/" # Supports non-YT sites

View file

@ -1,5 +1,6 @@
from typing import Any
from typing import Dict
from typing import Iterable
from typing import Optional
from typing import Set
@ -88,6 +89,24 @@ class Overrides(UnstructuredDictFormatterValidator, Scriptable):
return True
def ensure_variable_names_not_a_plugin(self, plugin_names: Iterable[str]) -> None:
"""
Throws an error if an override variable or function has the same name as a
preset key. This is to avoid confusion when accidentally defining things in
overrides that are meant to be in the preset.
"""
for name in self.keys:
if name.startswith("%"):
name = name[1:]
if name in plugin_names:
raise self._validation_exception(
f"Override variable with name {name} cannot be used since it is"
" the name of a plugin. Perhaps you meant to define it as a plugin? If so,"
" indent it left to make it at the same level as overrides.",
exception_class=InvalidVariableNameException,
)
def ensure_variable_name_valid(self, name: str) -> None:
"""
Ensures the variable name does not collide with any entry variables or built-in functions.

View file

@ -194,6 +194,8 @@ class Preset(_PresetShell):
self.plugins: PresetPlugins = self._validate_and_get_plugins()
self.overrides = self._validate_key(key="overrides", validator=Overrides, default={})
self.overrides.ensure_variable_names_not_a_plugin(plugin_names=PRESET_KEYS)
VariableValidation(
downloader_options=self.downloader_options,
output_options=self.output_options,

View file

@ -11,9 +11,6 @@ from ytdl_sub.entries.script.variable_types import Variable
from ytdl_sub.script.functions import Functions
from ytdl_sub.script.utils.name_validation import is_valid_name
# TODO: use this
SUBSCRIPTION_ARRAY = "subscription_array"
class SubscriptionVariables:
@staticmethod
@ -163,7 +160,7 @@ class OverrideHelpers:
True if the override name itself is valid. False otherwise.
"""
if name.startswith("%"):
return is_valid_name(name=name[1:])
name = name[1:]
return is_valid_name(name=name)

View file

@ -11,8 +11,7 @@ presets:
# Set the default date_range to 2 months
overrides:
date_range: "2months" # keep for legacy-reasons
only_recent_date_range: "{date_range}"
only_recent_date_range: "2months"
#############################################################################
# Only Recent

View file

@ -435,3 +435,27 @@ class TestPreset:
"output_options": {"output_directory": "dir", "file_name": "acjk"},
},
)
def test_preset_error_override_name_conflicts_with_plugin(self, config_file, output_options):
with pytest.raises(
ValidationException,
match=re.escape(
"Override variable with name throttle_protection cannot be used since it is the "
"name of a plugin. Perhaps you meant to define it as a plugin? If so, indent it "
"left to make it at the same level as overrides."
),
):
_ = Preset(
config=config_file,
name="test",
value={
"download": {
"url": "youtube.com/watch?v=123abc",
},
"subtitles": {
"embed_subtitles": True,
},
"output_options": {"output_directory": "dir", "file_name": "acjk"},
"overrides": {"throttle_protection": "nope"},
},
)