From dfcbadb69d01d3e2fe43429a07aa8be78120bca2 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Sat, 3 May 2025 21:46:31 -0700 Subject: [PATCH] [BACKEND] Make kodi_safe nfo overrideable (#1216) For an upcoming change to make preset selection easier --- Makefile | 6 +++--- docs/source/config_reference/plugins.rst | 4 ++-- src/ytdl_sub/config/overrides.py | 9 +++++++++ src/ytdl_sub/config/plugin/plugin.py | 5 +---- src/ytdl_sub/downloaders/url/downloader.py | 9 +++------ src/ytdl_sub/plugins/date_range.py | 5 +---- src/ytdl_sub/plugins/filter_exclude.py | 8 +++----- src/ytdl_sub/plugins/filter_include.py | 4 ++-- src/ytdl_sub/plugins/nfo_tags.py | 13 ++++++------- 9 files changed, 30 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index 6bdc1e1a..938e8fe7 100644 --- a/Makefile +++ b/Makefile @@ -14,9 +14,9 @@ else endif lint: - python3 -m isort . && \ - python3 -m black . && \ - python3 -m pylint src + python3 -m isort . + python3 -m black . + python3 -m pylint src check_lint: isort . --check-only --diff \ && black . --check \ diff --git a/docs/source/config_reference/plugins.rst b/docs/source/config_reference/plugins.rst index c3161a27..69afce80 100644 --- a/docs/source/config_reference/plugins.rst +++ b/docs/source/config_reference/plugins.rst @@ -456,7 +456,7 @@ with a ``.nfo`` extension. You can add any values into the NFO. ``kodi_safe`` -:expected type: Optional[Boolean] +:expected type: OverridesBooleanFormatterValidator :description: Defaults to False. Kodi does not support > 3-byte unicode characters, which include emojis and some foreign language characters. Setting this to True will replace those @@ -554,7 +554,7 @@ Usage: ``kodi_safe`` -:expected type: Optional[Boolean] +:expected type: OverridesBooleanFormatterValidator :description: Defaults to False. Kodi does not support > 3-byte unicode characters, which include emojis and some foreign language characters. Setting this to True will replace those diff --git a/src/ytdl_sub/config/overrides.py b/src/ytdl_sub/config/overrides.py index 9b7a4372..8ed6990c 100644 --- a/src/ytdl_sub/config/overrides.py +++ b/src/ytdl_sub/config/overrides.py @@ -221,3 +221,12 @@ class Overrides(UnstructuredDictFormatterValidator, Scriptable): return self._apply_to_resolvable( formatter=formatter, entry=None, function_overrides=None ).native + + def evaluate_boolean( + self, formatter: StringFormatterValidator, entry: Optional[Entry] = None + ) -> bool: + """ + Apply a formatter, and evaluate it to a boolean + """ + output = self.apply_formatter(formatter=formatter, entry=entry) + return ScriptUtils.bool_formatter_output(output) diff --git a/src/ytdl_sub/config/plugin/plugin.py b/src/ytdl_sub/config/plugin/plugin.py index 13feb41d..6b5929c1 100644 --- a/src/ytdl_sub/config/plugin/plugin.py +++ b/src/ytdl_sub/config/plugin/plugin.py @@ -13,7 +13,6 @@ from ytdl_sub.config.validators.options import OptionsValidatorT from ytdl_sub.config.validators.options import ToggleableOptionsDictValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.utils.file_handler import FileMetadata -from ytdl_sub.utils.script import ScriptUtils from ytdl_sub.ytdl_additions.enhanced_download_archive import DownloadArchiver from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive @@ -49,9 +48,7 @@ class Plugin(BasePlugin[OptionsValidatorT], Generic[OptionsValidatorT], ABC): Returns True if enabled, False if disabled. """ if isinstance(self.plugin_options, ToggleableOptionsDictValidator): - return ScriptUtils.bool_formatter_output( - self.overrides.apply_formatter(self.plugin_options.enable) - ) + return self.overrides.evaluate_boolean(self.plugin_options.enable) return True def ytdl_options_match_filters(self) -> Tuple[List[str], List[str]]: diff --git a/src/ytdl_sub/downloaders/url/downloader.py b/src/ytdl_sub/downloaders/url/downloader.py index f0595945..2db75fb1 100644 --- a/src/ytdl_sub/downloaders/url/downloader.py +++ b/src/ytdl_sub/downloaders/url/downloader.py @@ -25,7 +25,6 @@ from ytdl_sub.entries.script.variable_definitions import VARIABLES from ytdl_sub.entries.script.variable_definitions import VariableDefinitions from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.logger import Logger -from ytdl_sub.utils.script import ScriptUtils from ytdl_sub.utils.thumbnail import ThumbnailTypes from ytdl_sub.utils.thumbnail import download_and_convert_url_thumbnail from ytdl_sub.utils.thumbnail import try_convert_download_thumbnail @@ -459,11 +458,9 @@ class MultiUrlDownloader(SourcePlugin[MultiUrlValidator]): metadata_ytdl_options = self.metadata_ytdl_options( ytdl_option_overrides=validator.ytdl_options.to_native_dict(self.overrides) ) - download_reversed = ScriptUtils.bool_formatter_output( - self.overrides.apply_formatter(validator.download_reverse) - ) - include_sibling_metadata = ScriptUtils.bool_formatter_output( - self.overrides.apply_formatter(validator.include_sibling_metadata) + download_reversed = self.overrides.evaluate_boolean(validator.download_reverse) + include_sibling_metadata = self.overrides.evaluate_boolean( + validator.include_sibling_metadata ) parents, orphan_entries = self._download_url_metadata( diff --git a/src/ytdl_sub/plugins/date_range.py b/src/ytdl_sub/plugins/date_range.py index 27b9c808..b8b73711 100644 --- a/src/ytdl_sub/plugins/date_range.py +++ b/src/ytdl_sub/plugins/date_range.py @@ -5,7 +5,6 @@ from typing import Tuple from ytdl_sub.config.plugin.plugin import Plugin from ytdl_sub.config.validators.options import ToggleableOptionsDictValidator from ytdl_sub.utils.datetime import to_date_str -from ytdl_sub.utils.script import ScriptUtils from ytdl_sub.validators.string_datetime import StringDatetimeValidator from ytdl_sub.validators.string_formatter_validators import OverridesBooleanFormatterValidator @@ -95,9 +94,7 @@ class DateRangePlugin(Plugin[DateRangeOptions]): date_validator=self.plugin_options.after, overrides=self.overrides ) after_filter = f"upload_date >= {after_str}" - if ScriptUtils.bool_formatter_output( - self.overrides.apply_formatter(self.plugin_options.breaks) - ): + if self.overrides.evaluate_boolean(self.plugin_options.breaks): breaking_match_filters.append(after_filter) else: match_filters.append(after_filter) diff --git a/src/ytdl_sub/plugins/filter_exclude.py b/src/ytdl_sub/plugins/filter_exclude.py index 08f13939..7d256998 100644 --- a/src/ytdl_sub/plugins/filter_exclude.py +++ b/src/ytdl_sub/plugins/filter_exclude.py @@ -7,7 +7,6 @@ from ytdl_sub.config.validators.options import OptionsValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.utils.exceptions import StringFormattingException from ytdl_sub.utils.logger import Logger -from ytdl_sub.utils.script import ScriptUtils from ytdl_sub.validators.string_formatter_validators import ListFormatterValidator from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive @@ -53,10 +52,9 @@ class FilterExcludePlugin(Plugin[FilterExcludeOptions]): return entry for formatter in self.plugin_options.list: - out = ScriptUtils.bool_formatter_output( - self.overrides.apply_formatter(formatter=formatter, entry=entry) - ) - if bool(out): + should_exclude = self.overrides.evaluate_boolean(formatter=formatter, entry=entry) + + if should_exclude: logger.info( "Filtering '%s' from the filter %s evaluating to True", entry.title, diff --git a/src/ytdl_sub/plugins/filter_include.py b/src/ytdl_sub/plugins/filter_include.py index 5f7fcc4a..c2bc5217 100644 --- a/src/ytdl_sub/plugins/filter_include.py +++ b/src/ytdl_sub/plugins/filter_include.py @@ -61,10 +61,10 @@ class FilterIncludePlugin(Plugin[FilterIncludeOptions]): return entry for formatter in self.plugin_options.list: - out = ScriptUtils.bool_formatter_output( + should_exclude = ScriptUtils.bool_formatter_output( self.overrides.apply_formatter(formatter=formatter, entry=entry) ) - if not bool(out): + if not should_exclude: logger.info( "Filtering '%s' from the filter %s evaluating to False", entry.title, diff --git a/src/ytdl_sub/plugins/nfo_tags.py b/src/ytdl_sub/plugins/nfo_tags.py index 86fe6568..24c07c72 100644 --- a/src/ytdl_sub/plugins/nfo_tags.py +++ b/src/ytdl_sub/plugins/nfo_tags.py @@ -5,7 +5,6 @@ from pathlib import Path from typing import Any from typing import Dict from typing import List -from typing import Optional from ytdl_sub.config.plugin.plugin import Plugin from ytdl_sub.config.validators.options import ToggleableOptionsDictValidator @@ -19,8 +18,8 @@ from ytdl_sub.utils.xml import to_xml from ytdl_sub.validators.file_path_validators import StringFormatterFileNameValidator from ytdl_sub.validators.nfo_validators import NfoTagsValidator from ytdl_sub.validators.string_formatter_validators import DictFormatterValidator +from ytdl_sub.validators.string_formatter_validators import OverridesBooleanFormatterValidator from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator -from ytdl_sub.validators.validators import BoolValidator class SharedNfoTagsOptions(ToggleableOptionsDictValidator): @@ -54,8 +53,8 @@ class SharedNfoTagsOptions(ToggleableOptionsDictValidator): ) self._tags = self._validate_key_if_present(key="tags", validator=NfoTagsValidator) self._kodi_safe = self._validate_key_if_present( - key="kodi_safe", validator=BoolValidator, default=False - ).value + key="kodi_safe", validator=OverridesBooleanFormatterValidator, default="False" + ) @property def nfo_name(self) -> StringFormatterFileNameValidator: @@ -81,9 +80,9 @@ class SharedNfoTagsOptions(ToggleableOptionsDictValidator): return self._tags @property - def kodi_safe(self) -> Optional[bool]: + def kodi_safe(self) -> OverridesBooleanFormatterValidator: """ - :expected type: Optional[Boolean] + :expected type: OverridesBooleanFormatterValidator :description: Defaults to False. Kodi does not support > 3-byte unicode characters, which include emojis and some foreign language characters. Setting this to True will replace those @@ -141,7 +140,7 @@ class SharedNfoTagsPlugin(Plugin[SharedNfoTagsOptions], ABC): if not nfo_tags: return - if self.plugin_options.kodi_safe: + if self.overrides.evaluate_boolean(self.plugin_options.kodi_safe): nfo_root = to_max_3_byte_utf8_string(nfo_root) nfo_tags = { to_max_3_byte_utf8_string(key): [