[BACKEND] Make kodi_safe nfo overrideable (#1216)

For an upcoming change to make preset selection easier
This commit is contained in:
Jesse Bannon 2025-05-03 21:46:31 -07:00 committed by GitHub
parent d5e8157b6c
commit dfcbadb69d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 30 additions and 33 deletions

View file

@ -14,9 +14,9 @@ else
endif endif
lint: lint:
python3 -m isort . && \ python3 -m isort .
python3 -m black . && \ python3 -m black .
python3 -m pylint src python3 -m pylint src
check_lint: check_lint:
isort . --check-only --diff \ isort . --check-only --diff \
&& black . --check \ && black . --check \

View file

@ -456,7 +456,7 @@ with a ``.nfo`` extension. You can add any values into the NFO.
``kodi_safe`` ``kodi_safe``
:expected type: Optional[Boolean] :expected type: OverridesBooleanFormatterValidator
:description: :description:
Defaults to False. Kodi does not support > 3-byte unicode characters, which include 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 emojis and some foreign language characters. Setting this to True will replace those
@ -554,7 +554,7 @@ Usage:
``kodi_safe`` ``kodi_safe``
:expected type: Optional[Boolean] :expected type: OverridesBooleanFormatterValidator
:description: :description:
Defaults to False. Kodi does not support > 3-byte unicode characters, which include 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 emojis and some foreign language characters. Setting this to True will replace those

View file

@ -221,3 +221,12 @@ class Overrides(UnstructuredDictFormatterValidator, Scriptable):
return self._apply_to_resolvable( return self._apply_to_resolvable(
formatter=formatter, entry=None, function_overrides=None formatter=formatter, entry=None, function_overrides=None
).native ).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)

View file

@ -13,7 +13,6 @@ from ytdl_sub.config.validators.options import OptionsValidatorT
from ytdl_sub.config.validators.options import ToggleableOptionsDictValidator from ytdl_sub.config.validators.options import ToggleableOptionsDictValidator
from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.entry import Entry
from ytdl_sub.utils.file_handler import FileMetadata 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 DownloadArchiver
from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive 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. Returns True if enabled, False if disabled.
""" """
if isinstance(self.plugin_options, ToggleableOptionsDictValidator): if isinstance(self.plugin_options, ToggleableOptionsDictValidator):
return ScriptUtils.bool_formatter_output( return self.overrides.evaluate_boolean(self.plugin_options.enable)
self.overrides.apply_formatter(self.plugin_options.enable)
)
return True return True
def ytdl_options_match_filters(self) -> Tuple[List[str], List[str]]: def ytdl_options_match_filters(self) -> Tuple[List[str], List[str]]:

View file

@ -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.entries.script.variable_definitions import VariableDefinitions
from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.logger import Logger 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 ThumbnailTypes
from ytdl_sub.utils.thumbnail import download_and_convert_url_thumbnail from ytdl_sub.utils.thumbnail import download_and_convert_url_thumbnail
from ytdl_sub.utils.thumbnail import try_convert_download_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( metadata_ytdl_options = self.metadata_ytdl_options(
ytdl_option_overrides=validator.ytdl_options.to_native_dict(self.overrides) ytdl_option_overrides=validator.ytdl_options.to_native_dict(self.overrides)
) )
download_reversed = ScriptUtils.bool_formatter_output( download_reversed = self.overrides.evaluate_boolean(validator.download_reverse)
self.overrides.apply_formatter(validator.download_reverse) include_sibling_metadata = self.overrides.evaluate_boolean(
) validator.include_sibling_metadata
include_sibling_metadata = ScriptUtils.bool_formatter_output(
self.overrides.apply_formatter(validator.include_sibling_metadata)
) )
parents, orphan_entries = self._download_url_metadata( parents, orphan_entries = self._download_url_metadata(

View file

@ -5,7 +5,6 @@ from typing import Tuple
from ytdl_sub.config.plugin.plugin import Plugin from ytdl_sub.config.plugin.plugin import Plugin
from ytdl_sub.config.validators.options import ToggleableOptionsDictValidator from ytdl_sub.config.validators.options import ToggleableOptionsDictValidator
from ytdl_sub.utils.datetime import to_date_str 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_datetime import StringDatetimeValidator
from ytdl_sub.validators.string_formatter_validators import OverridesBooleanFormatterValidator 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 date_validator=self.plugin_options.after, overrides=self.overrides
) )
after_filter = f"upload_date >= {after_str}" after_filter = f"upload_date >= {after_str}"
if ScriptUtils.bool_formatter_output( if self.overrides.evaluate_boolean(self.plugin_options.breaks):
self.overrides.apply_formatter(self.plugin_options.breaks)
):
breaking_match_filters.append(after_filter) breaking_match_filters.append(after_filter)
else: else:
match_filters.append(after_filter) match_filters.append(after_filter)

View file

@ -7,7 +7,6 @@ from ytdl_sub.config.validators.options import OptionsValidator
from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.entry import Entry
from ytdl_sub.utils.exceptions import StringFormattingException from ytdl_sub.utils.exceptions import StringFormattingException
from ytdl_sub.utils.logger import Logger 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.validators.string_formatter_validators import ListFormatterValidator
from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive
@ -53,10 +52,9 @@ class FilterExcludePlugin(Plugin[FilterExcludeOptions]):
return entry return entry
for formatter in self.plugin_options.list: for formatter in self.plugin_options.list:
out = ScriptUtils.bool_formatter_output( should_exclude = self.overrides.evaluate_boolean(formatter=formatter, entry=entry)
self.overrides.apply_formatter(formatter=formatter, entry=entry)
) if should_exclude:
if bool(out):
logger.info( logger.info(
"Filtering '%s' from the filter %s evaluating to True", "Filtering '%s' from the filter %s evaluating to True",
entry.title, entry.title,

View file

@ -61,10 +61,10 @@ class FilterIncludePlugin(Plugin[FilterIncludeOptions]):
return entry return entry
for formatter in self.plugin_options.list: 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) self.overrides.apply_formatter(formatter=formatter, entry=entry)
) )
if not bool(out): if not should_exclude:
logger.info( logger.info(
"Filtering '%s' from the filter %s evaluating to False", "Filtering '%s' from the filter %s evaluating to False",
entry.title, entry.title,

View file

@ -5,7 +5,6 @@ from pathlib import Path
from typing import Any from typing import Any
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Optional
from ytdl_sub.config.plugin.plugin import Plugin from ytdl_sub.config.plugin.plugin import Plugin
from ytdl_sub.config.validators.options import ToggleableOptionsDictValidator 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.file_path_validators import StringFormatterFileNameValidator
from ytdl_sub.validators.nfo_validators import NfoTagsValidator 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 DictFormatterValidator
from ytdl_sub.validators.string_formatter_validators import OverridesBooleanFormatterValidator
from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator
from ytdl_sub.validators.validators import BoolValidator
class SharedNfoTagsOptions(ToggleableOptionsDictValidator): class SharedNfoTagsOptions(ToggleableOptionsDictValidator):
@ -54,8 +53,8 @@ class SharedNfoTagsOptions(ToggleableOptionsDictValidator):
) )
self._tags = self._validate_key_if_present(key="tags", validator=NfoTagsValidator) self._tags = self._validate_key_if_present(key="tags", validator=NfoTagsValidator)
self._kodi_safe = self._validate_key_if_present( self._kodi_safe = self._validate_key_if_present(
key="kodi_safe", validator=BoolValidator, default=False key="kodi_safe", validator=OverridesBooleanFormatterValidator, default="False"
).value )
@property @property
def nfo_name(self) -> StringFormatterFileNameValidator: def nfo_name(self) -> StringFormatterFileNameValidator:
@ -81,9 +80,9 @@ class SharedNfoTagsOptions(ToggleableOptionsDictValidator):
return self._tags return self._tags
@property @property
def kodi_safe(self) -> Optional[bool]: def kodi_safe(self) -> OverridesBooleanFormatterValidator:
""" """
:expected type: Optional[Boolean] :expected type: OverridesBooleanFormatterValidator
:description: :description:
Defaults to False. Kodi does not support > 3-byte unicode characters, which include 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 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: if not nfo_tags:
return 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_root = to_max_3_byte_utf8_string(nfo_root)
nfo_tags = { nfo_tags = {
to_max_3_byte_utf8_string(key): [ to_max_3_byte_utf8_string(key): [