[BACKEND] More flexible formatter post_process

This commit is contained in:
Jesse Bannon 2026-01-23 14:41:43 -08:00
parent 264e458c1c
commit 081d76c4e4
7 changed files with 12 additions and 62 deletions

View file

@ -20,7 +20,6 @@ from ytdl_sub.utils.exceptions import StringFormattingException
from ytdl_sub.utils.exceptions import ValidationException from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.script import ScriptUtils from ytdl_sub.utils.script import ScriptUtils
from ytdl_sub.utils.scriptable import Scriptable from ytdl_sub.utils.scriptable import Scriptable
from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator
from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator
from ytdl_sub.validators.string_formatter_validators import UnstructuredDictFormatterValidator from ytdl_sub.validators.string_formatter_validators import UnstructuredDictFormatterValidator
@ -207,7 +206,7 @@ class Overrides(UnstructuredDictFormatterValidator, Scriptable):
formatter: StringFormatterValidator, formatter: StringFormatterValidator,
entry: Optional[Entry] = None, entry: Optional[Entry] = None,
function_overrides: Optional[Dict[str, str]] = None, function_overrides: Optional[Dict[str, str]] = None,
) -> str: ) -> Any:
""" """
Parameters Parameters
---------- ----------
@ -228,33 +227,8 @@ class Overrides(UnstructuredDictFormatterValidator, Scriptable):
If the formatter that is trying to be resolved cannot If the formatter that is trying to be resolved cannot
""" """
return formatter.post_process( return formatter.post_process(
str(
self._apply_to_resolvable( self._apply_to_resolvable(
formatter=formatter, entry=entry, function_overrides=function_overrides formatter=formatter, entry=entry, function_overrides=function_overrides
)
)
)
def apply_overrides_formatter_to_native(
self,
formatter: OverridesStringFormatterValidator,
function_overrides: Optional[Dict[str, str]] = None,
) -> Any:
"""
Parameters
----------
formatter
Overrides formatter to apply
function_overrides
Optional. Explicit values to override the overrides themselves and source variables
Returns
-------
The native python form of the resolved variable
"""
return formatter.post_process_native(
self._apply_to_resolvable(
formatter=formatter, entry=None, function_overrides=function_overrides
).native ).native
) )

View file

@ -62,10 +62,7 @@ class YTDLOptions(UnstructuredOverridesDictFormatterValidator):
Materializes the entire ytdl-options dict from OverrideStringFormatters into Materializes the entire ytdl-options dict from OverrideStringFormatters into
native python. native python.
""" """
out = { out = {key: overrides.apply_formatter(val) for key, val in self.dict.items()}
key: overrides.apply_overrides_formatter_to_native(val)
for key, val in self.dict.items()
}
if "cookiefile" in out: if "cookiefile" in out:
if not FileHandler.is_file_existent(out["cookiefile"]): if not FileHandler.is_file_existent(out["cookiefile"]):
raise ValidationException( raise ValidationException(

View file

@ -52,12 +52,12 @@ class UrlDownloaderBasePluginExtension(SourcePluginExtension[MultiUrlValidator])
if 0 <= input_url_idx < len(self.plugin_options.urls.list): if 0 <= input_url_idx < len(self.plugin_options.urls.list):
validator = self.plugin_options.urls.list[input_url_idx] validator = self.plugin_options.urls.list[input_url_idx]
if entry_input_url in self.overrides.apply_overrides_formatter_to_native(validator.url): if entry_input_url in self.overrides.apply_formatter(validator.url):
return validator return validator
# Match the first validator based on the URL, if one exists # Match the first validator based on the URL, if one exists
for validator in self.plugin_options.urls.list: for validator in self.plugin_options.urls.list:
if entry_input_url in self.overrides.apply_overrides_formatter_to_native(validator.url): if entry_input_url in self.overrides.apply_formatter(validator.url):
return validator return validator
# Return the first validator if none exist # Return the first validator if none exist
@ -487,7 +487,7 @@ class MultiUrlDownloader(SourcePlugin[MultiUrlValidator]):
# download the bottom-most urls first since they are top-priority # download the bottom-most urls first since they are top-priority
for idx, url_validator in reversed(list(enumerate(self.collection.urls.list))): for idx, url_validator in reversed(list(enumerate(self.collection.urls.list))):
# URLs can be empty. If they are, then skip # URLs can be empty. If they are, then skip
if not (urls := self.overrides.apply_overrides_formatter_to_native(url_validator.url)): if not (urls := self.overrides.apply_formatter(url_validator.url)):
continue continue
assert isinstance(urls, list) assert isinstance(urls, list)

View file

@ -44,7 +44,7 @@ class UrlThumbnailListValidator(ListValidator[UrlThumbnailValidator]):
class OverridesOneOrManyUrlValidator(OverridesStringFormatterValidator): class OverridesOneOrManyUrlValidator(OverridesStringFormatterValidator):
def post_process_native(self, resolved: Any) -> Any: def post_process(self, resolved: Any) -> Any:
if isinstance(resolved, str): if isinstance(resolved, str):
return [resolved] return [resolved]
if isinstance(resolved, list): if isinstance(resolved, list):

View file

@ -82,21 +82,13 @@ class StringFormatterValidator(StringValidator):
""" """
return self._parsed return self._parsed
def post_process(self, resolved: str) -> str: def post_process(self, resolved: Any) -> Any:
""" """
Returns Returns
------- -------
Apply any post processing to the resolved value Apply any post processing to the resolved value. Defaults to casting it to string.
""" """
return resolved return str(resolved)
def post_process_native(self, resolved: Any) -> Any:
"""
Returns
-------
Apply any post processing to the resolved native value.
"""
return resolved
class FloatFormatterValidator(StringFormatterValidator): class FloatFormatterValidator(StringFormatterValidator):

View file

@ -475,19 +475,6 @@ def test_advanced_tv_show_subscriptions(
assert overrides.script.get("subscription_name").native == "Gardening with Ciscoe" assert overrides.script.get("subscription_name").native == "Gardening with Ciscoe"
assert overrides.apply_overrides_formatter_to_native(overrides.dict["subscription_array"]) == [
"https://www.youtube.com/@gardeningwithciscoe4430",
"https://www.youtube.com/playlist?list=PLi8V8UemxeG6lo5if5H5g5EbsteELcb0_",
"https://www.youtube.com/playlist?list=PLsJlQSR-KjmaQqqJ9jq18cF6XXXAR4kyn",
"https://www.youtube.com/watch?v=2vq-vPubS5I",
]
assert overrides.apply_overrides_formatter_to_native(overrides.dict["urls"]) == [
"https://www.youtube.com/@gardeningwithciscoe4430",
"https://www.youtube.com/playlist?list=PLi8V8UemxeG6lo5if5H5g5EbsteELcb0_",
"https://www.youtube.com/playlist?list=PLsJlQSR-KjmaQqqJ9jq18cF6XXXAR4kyn",
"https://www.youtube.com/watch?v=2vq-vPubS5I",
]
def test_music_subscriptions(default_config: ConfigFile, music_subscriptions_path: Path): def test_music_subscriptions(default_config: ConfigFile, music_subscriptions_path: Path):
subs = Subscription.from_file_path( subs = Subscription.from_file_path(

View file

@ -57,7 +57,7 @@ class TestTvShowCollectionPreset:
# is_bilateral # is_bilateral
if i == 0: if i == 0:
url = sub.overrides.apply_overrides_formatter_to_native( url = sub.overrides.apply_formatter(
url_list[itr].url, url_list[itr].url,
function_overrides={ function_overrides={
# mock so bilateral url gets enabled # mock so bilateral url gets enabled
@ -81,7 +81,7 @@ class TestTvShowCollectionPreset:
# not bilateral # not bilateral
else: else:
for j in range(2): for j in range(2):
url = sub.overrides.apply_overrides_formatter_to_native( url = sub.overrides.apply_formatter(
url_list[itr + j].url, url_list[itr + j].url,
function_overrides={ function_overrides={
# mock so bilateral url gets enabled # mock so bilateral url gets enabled