diff --git a/src/ytdl_sub/config/preset.py b/src/ytdl_sub/config/preset.py index 5b8b107c..44d7b66d 100644 --- a/src/ytdl_sub/config/preset.py +++ b/src/ytdl_sub/config/preset.py @@ -13,6 +13,7 @@ from mergedeep import mergedeep from ytdl_sub.config.config_validator import ConfigValidator from ytdl_sub.config.preset_class_mappings import DownloadStrategyMapping from ytdl_sub.config.preset_class_mappings import PluginMapping +from ytdl_sub.config.preset_options import OptionsValidator from ytdl_sub.config.preset_options import OutputOptions from ytdl_sub.config.preset_options import Overrides from ytdl_sub.config.preset_options import YTDLOptions @@ -20,7 +21,6 @@ from ytdl_sub.downloaders.base_downloader import BaseDownloader from ytdl_sub.downloaders.base_downloader import BaseDownloaderValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.plugins.plugin import PluginOptionsT from ytdl_sub.prebuilt_presets import PREBUILT_PRESET_NAMES from ytdl_sub.prebuilt_presets import PUBLISHED_PRESET_NAMES @@ -67,9 +67,9 @@ def _parent_preset_error_message( class PresetPlugins: def __init__(self): self.plugin_types: List[Type[Plugin]] = [] - self.plugin_options: List[PluginOptions] = [] + self.plugin_options: List[OptionsValidator] = [] - def add(self, plugin_type: Type[Plugin], plugin_options: PluginOptions) -> "PresetPlugins": + def add(self, plugin_type: Type[Plugin], plugin_options: OptionsValidator) -> "PresetPlugins": """ Add a pair of plugin type and options to the list """ @@ -77,7 +77,7 @@ class PresetPlugins: self.plugin_options.append(plugin_options) return self - def zipped(self) -> Iterable[Tuple[Type[Plugin], PluginOptions]]: + def zipped(self) -> Iterable[Tuple[Type[Plugin], OptionsValidator]]: """ Returns ------- diff --git a/src/ytdl_sub/config/preset_options.py b/src/ytdl_sub/config/preset_options.py index 72f1b281..d9ba7f9c 100644 --- a/src/ytdl_sub/config/preset_options.py +++ b/src/ytdl_sub/config/preset_options.py @@ -18,11 +18,12 @@ from ytdl_sub.validators.string_formatter_validators import OverridesStringForma from ytdl_sub.validators.string_formatter_validators import StringFormatterValidator from ytdl_sub.validators.validators import BoolValidator from ytdl_sub.validators.validators import LiteralDictValidator +from ytdl_sub.validators.validators import Validator # pylint: disable=no-self-use # pylint: disable=unused-argument -class OptionsValidator(StrictDictValidator, ABC): +class OptionsValidator(Validator, ABC): """ Abstract class that validates options for preset sections (plugins, downloaders) """ @@ -70,6 +71,10 @@ class OptionsValidator(StrictDictValidator, ABC): return None +class OptionsDictValidator(StrictDictValidator, OptionsValidator, ABC): + pass + + # pylint: enable=no-self-use # pylint: enable=unused-argument diff --git a/src/ytdl_sub/downloaders/base_downloader.py b/src/ytdl_sub/downloaders/base_downloader.py index 73759af0..dd105fb7 100644 --- a/src/ytdl_sub/downloaders/base_downloader.py +++ b/src/ytdl_sub/downloaders/base_downloader.py @@ -6,7 +6,7 @@ from typing import List from typing import Type from typing import TypeVar -from ytdl_sub.config.preset_options import OptionsValidator +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.config.preset_options import Overrides from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder from ytdl_sub.entries.entry import Entry @@ -14,7 +14,7 @@ from ytdl_sub.plugins.plugin import Plugin from ytdl_sub.ytdl_additions.enhanced_download_archive import DownloadArchiver from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive -BaseDownloaderValidator = OptionsValidator +BaseDownloaderValidator = OptionsDictValidator BaseDownloaderOptionsT = TypeVar("BaseDownloaderOptionsT", bound=BaseDownloaderValidator) diff --git a/src/ytdl_sub/downloaders/url/validators.py b/src/ytdl_sub/downloaders/url/validators.py index 52e5f367..53486117 100644 --- a/src/ytdl_sub/downloaders/url/validators.py +++ b/src/ytdl_sub/downloaders/url/validators.py @@ -3,7 +3,7 @@ from typing import Dict from typing import List from typing import Optional -from ytdl_sub.config.preset_options import OptionsValidator +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.validators.strict_dict_validator import StrictDictValidator from ytdl_sub.validators.string_formatter_validators import DictFormatterValidator from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator @@ -172,7 +172,7 @@ class UrlListValidator(ListValidator[UrlValidator]): collection_variables[var] = added_variables[var] -class MultiUrlValidator(OptionsValidator): +class MultiUrlValidator(OptionsDictValidator): """ Downloads from multiple URLs. If an entry is returned from more than one URL, it will resolve to the bottom-most URL settings. diff --git a/src/ytdl_sub/plugins/audio_extract.py b/src/ytdl_sub/plugins/audio_extract.py index 0840a37d..de4b2058 100644 --- a/src/ytdl_sub/plugins/audio_extract.py +++ b/src/ytdl_sub/plugins/audio_extract.py @@ -3,17 +3,17 @@ from typing import Any from typing import Dict from typing import Optional +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder from ytdl_sub.entries.entry import Entry from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.utils.exceptions import FileNotDownloadedException from ytdl_sub.validators.audo_codec_validator import AUDIO_CODEC_TYPES_EXTENSION_MAPPING from ytdl_sub.validators.audo_codec_validator import AudioTypeValidator from ytdl_sub.validators.validators import FloatValidator -class AudioExtractOptions(PluginOptions): +class AudioExtractOptions(OptionsDictValidator): """ Extracts audio from a video file. diff --git a/src/ytdl_sub/plugins/chapters.py b/src/ytdl_sub/plugins/chapters.py index 2385b8a9..03928f68 100644 --- a/src/ytdl_sub/plugins/chapters.py +++ b/src/ytdl_sub/plugins/chapters.py @@ -5,12 +5,12 @@ from typing import List from typing import Optional from typing import Set +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.variables.kwargs import COMMENTS from ytdl_sub.entries.variables.kwargs import YTDL_SUB_CUSTOM_CHAPTERS from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.utils.chapters import Chapters from ytdl_sub.utils.ffmpeg import set_ffmpeg_metadata_chapters from ytdl_sub.utils.file_handler import FileMetadata @@ -58,7 +58,7 @@ class SponsorBlockCategoryListValidator(ListValidator[SponsorBlockCategoriesVali _inner_list_type = SponsorBlockCategoriesValidator -class ChaptersOptions(PluginOptions): +class ChaptersOptions(OptionsDictValidator): """ Embeds chapters to video files if they are present. Additional options to add SponsorBlock chapters and remove specific ones. Can also remove chapters using regex. diff --git a/src/ytdl_sub/plugins/date_range.py b/src/ytdl_sub/plugins/date_range.py index d86f5c2d..fb18d892 100644 --- a/src/ytdl_sub/plugins/date_range.py +++ b/src/ytdl_sub/plugins/date_range.py @@ -1,14 +1,14 @@ from typing import Dict from typing import Optional +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.utils.datetime import to_date_range from ytdl_sub.validators.string_datetime import StringDatetimeValidator -class DateRangeOptions(PluginOptions): +class DateRangeOptions(OptionsDictValidator): """ Only download files uploaded within the specified date range. diff --git a/src/ytdl_sub/plugins/file_convert.py b/src/ytdl_sub/plugins/file_convert.py index 3ae1ebcb..86c4a303 100644 --- a/src/ytdl_sub/plugins/file_convert.py +++ b/src/ytdl_sub/plugins/file_convert.py @@ -3,10 +3,10 @@ from typing import Any from typing import Dict from typing import Optional +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.variables.kwargs import EXT from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.plugins.plugin import PluginPriority from ytdl_sub.utils.exceptions import FileNotDownloadedException from ytdl_sub.utils.exceptions import ValidationException @@ -22,7 +22,7 @@ class FileConvertWithValidator(StringSelectValidator): _select_values = {"yt-dlp", "ffmpeg"} -class FileConvertOptions(PluginOptions): +class FileConvertOptions(OptionsDictValidator): """ Converts video files from one extension to another. diff --git a/src/ytdl_sub/plugins/internal/view.py b/src/ytdl_sub/plugins/internal/view.py index 66bef3e5..ff7946f7 100644 --- a/src/ytdl_sub/plugins/internal/view.py +++ b/src/ytdl_sub/plugins/internal/view.py @@ -1,17 +1,17 @@ import copy from typing import Optional +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.config.preset_options import Overrides from ytdl_sub.entries.entry import Entry from ytdl_sub.plugins.output_directory_nfo_tags import OutputDirectoryNfoTagsOptions from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.plugins.plugin import PluginPriority from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive -class ViewOptions(PluginOptions): +class ViewOptions(OptionsDictValidator): """ INTERNAL PLUGIN. Do not expose in documentation """ diff --git a/src/ytdl_sub/plugins/match_filters.py b/src/ytdl_sub/plugins/match_filters.py index ef7f2a47..8dd3ce5c 100644 --- a/src/ytdl_sub/plugins/match_filters.py +++ b/src/ytdl_sub/plugins/match_filters.py @@ -5,10 +5,10 @@ from typing import Optional from yt_dlp import match_filter_func +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.variables.kwargs import YTDL_SUB_MATCH_FILTER_REJECT from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.plugins.plugin import PluginPriority from ytdl_sub.utils.logger import Logger from ytdl_sub.validators.validators import StringListValidator @@ -16,7 +16,7 @@ from ytdl_sub.validators.validators import StringListValidator logger = Logger.get("match_filters") -class MatchFiltersOptions(PluginOptions): +class MatchFiltersOptions(OptionsDictValidator): """ Set ``--match-filters``` to pass into yt-dlp to filter entries from being downloaded. Uses the same syntax as yt-dlp. diff --git a/src/ytdl_sub/plugins/music_tags.py b/src/ytdl_sub/plugins/music_tags.py index 90b7889a..97280bd6 100644 --- a/src/ytdl_sub/plugins/music_tags.py +++ b/src/ytdl_sub/plugins/music_tags.py @@ -5,9 +5,9 @@ from typing import List import mediafile +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.utils.logger import Logger from ytdl_sub.utils.thumbnail import convert_download_thumbnail @@ -45,7 +45,7 @@ class MusicTagsValidator(StrictDictValidator): return self._tags -class MusicTagsOptions(PluginOptions): +class MusicTagsOptions(OptionsDictValidator): """ Adds tags to every download audio file using `MediaFile `_, diff --git a/src/ytdl_sub/plugins/nfo_tags.py b/src/ytdl_sub/plugins/nfo_tags.py index 395cc3f2..d76bf5c6 100644 --- a/src/ytdl_sub/plugins/nfo_tags.py +++ b/src/ytdl_sub/plugins/nfo_tags.py @@ -7,9 +7,9 @@ from typing import Dict from typing import List from typing import Optional +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.utils.xml import XmlElement @@ -23,7 +23,7 @@ from ytdl_sub.validators.string_formatter_validators import StringFormatterValid from ytdl_sub.validators.validators import BoolValidator -class SharedNfoTagsOptions(PluginOptions): +class SharedNfoTagsOptions(OptionsDictValidator): """ Shared code between NFO tags and Ouptut Directory NFO Tags """ diff --git a/src/ytdl_sub/plugins/plugin.py b/src/ytdl_sub/plugins/plugin.py index 35488dfd..5f5ec03c 100644 --- a/src/ytdl_sub/plugins/plugin.py +++ b/src/ytdl_sub/plugins/plugin.py @@ -40,8 +40,7 @@ class PluginPriority: return self.modify_entry >= PluginPriority.MODIFY_ENTRY_AFTER_SPLIT -PluginOptions = OptionsValidator -PluginOptionsT = TypeVar("PluginOptionsT", bound=PluginOptions) +PluginOptionsT = TypeVar("PluginOptionsT", bound=OptionsValidator) class Plugin(DownloadArchiver, Generic[PluginOptionsT], ABC): diff --git a/src/ytdl_sub/plugins/regex.py b/src/ytdl_sub/plugins/regex.py index 39485c10..fcafd258 100644 --- a/src/ytdl_sub/plugins/regex.py +++ b/src/ytdl_sub/plugins/regex.py @@ -5,10 +5,10 @@ from typing import Optional from yt_dlp.utils import sanitize_filename +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.variables.kwargs import YTDL_SUB_REGEX_SOURCE_VARS from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.plugins.plugin import PluginPriority from ytdl_sub.utils.exceptions import RegexNoMatchException from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException @@ -121,7 +121,7 @@ class FromSourceVariablesRegex(StrictDictValidator): } -class RegexOptions(PluginOptions): +class RegexOptions(OptionsDictValidator): r""" Performs regex matching on an entry's source or override variables. Regex can be used to filter entries from proceeding with download or capture groups to create new source variables. NOTE to diff --git a/src/ytdl_sub/plugins/split_by_chapters.py b/src/ytdl_sub/plugins/split_by_chapters.py index 201d02de..63fbb11f 100644 --- a/src/ytdl_sub/plugins/split_by_chapters.py +++ b/src/ytdl_sub/plugins/split_by_chapters.py @@ -8,13 +8,13 @@ from typing import Tuple from yt_dlp.utils import sanitize_filename +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.variables.kwargs import CHAPTERS from ytdl_sub.entries.variables.kwargs import SPLIT_BY_CHAPTERS_PARENT_ENTRY from ytdl_sub.entries.variables.kwargs import SPONSORBLOCK_CHAPTERS from ytdl_sub.entries.variables.kwargs import UID from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.utils.chapters import Chapters from ytdl_sub.utils.chapters import Timestamp from ytdl_sub.utils.exceptions import ValidationException @@ -47,7 +47,7 @@ class WhenNoChaptersValidator(StringSelectValidator): _select_values = {"pass", "drop", "error"} -class SplitByChaptersOptions(PluginOptions): +class SplitByChaptersOptions(OptionsDictValidator): """ Splits a file by chapters into multiple files. Each file becomes its own entry with the new source variables ``chapter_title``, ``chapter_title_sanitized``, ``chapter_index``, diff --git a/src/ytdl_sub/plugins/subtitles.py b/src/ytdl_sub/plugins/subtitles.py index 782361c5..03097863 100644 --- a/src/ytdl_sub/plugins/subtitles.py +++ b/src/ytdl_sub/plugins/subtitles.py @@ -3,10 +3,10 @@ from typing import Dict from typing import List from typing import Optional +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder from ytdl_sub.entries.entry import Entry from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.utils.logger import Logger @@ -25,7 +25,7 @@ class SubtitlesTypeValidator(StringSelectValidator): _select_values = SUBTITLE_EXTENSIONS -class SubtitleOptions(PluginOptions): +class SubtitleOptions(OptionsDictValidator): """ Defines how to download and store subtitles. Using this plugin creates two new variables: ``lang`` and ``subtitles_ext``. ``lang`` is dynamic since you can download multiple subtitles. diff --git a/src/ytdl_sub/plugins/video_tags.py b/src/ytdl_sub/plugins/video_tags.py index e1fb85a4..fc5366f6 100644 --- a/src/ytdl_sub/plugins/video_tags.py +++ b/src/ytdl_sub/plugins/video_tags.py @@ -1,15 +1,15 @@ from typing import Any from typing import Dict +from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.utils.ffmpeg import add_ffmpeg_metadata_key_values from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.validators.string_formatter_validators import DictFormatterValidator -class VideoTagsOptions(PluginOptions): +class VideoTagsOptions(OptionsDictValidator): """ Adds tags to every downloaded video file using ffmpeg ``-metadata key=value`` args.