diff --git a/src/ytdl_sub/plugins/plugin.py b/src/ytdl_sub/config/plugin.py similarity index 85% rename from src/ytdl_sub/plugins/plugin.py rename to src/ytdl_sub/config/plugin.py index 46d896d7..b6c4bf5e 100644 --- a/src/ytdl_sub/plugins/plugin.py +++ b/src/ytdl_sub/config/plugin.py @@ -1,4 +1,5 @@ from abc import ABC +from abc import abstractmethod from typing import Dict from typing import Generic from typing import List @@ -10,7 +11,6 @@ from ytdl_sub.config.preset_options import Overrides from ytdl_sub.config.preset_options import TOptionsValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.utils.file_handler import FileMetadata -from ytdl_sub.utils.logger import Logger from ytdl_sub.ytdl_additions.enhanced_download_archive import DownloadArchiver from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive @@ -42,30 +42,33 @@ class PluginPriority: return self.modify_entry >= PluginPriority.MODIFY_ENTRY_AFTER_SPLIT -class Plugin(DownloadArchiver, Generic[TOptionsValidator], ABC): +# pylint: disable=no-self-use,unused-argument + + +class BasePlugin(DownloadArchiver, Generic[TOptionsValidator], ABC): """ - Class to define the new plugin functionality + Shared code amongst all SourcePlugins (downloaders) and Plugins (post-download modification) """ - plugin_options_type: Type[TOptionsValidator] = NotImplemented priority: PluginPriority = PluginPriority() - - # If the plugin creates multiple entries from a single entry - is_split_plugin: bool = False + plugin_options_type: Type[TOptionsValidator] def __init__( self, - plugin_options: TOptionsValidator, + options: TOptionsValidator, overrides: Overrides, enhanced_download_archive: EnhancedDownloadArchive, ): DownloadArchiver.__init__(self=self, enhanced_download_archive=enhanced_download_archive) - self.plugin_options = plugin_options + self.plugin_options = options self.overrides = overrides - # TODO pass yaml snake case name in the class somewhere, and use it for the logger - self._logger = Logger.get(self.__class__.__name__) - # pylint: disable=no-self-use,unused-argument + +class Plugin(BasePlugin[TOptionsValidator], Generic[TOptionsValidator], ABC): + """ + Class to define the new plugin functionality + """ + def ytdl_options(self) -> Optional[Dict]: """ Returns @@ -73,22 +76,6 @@ class Plugin(DownloadArchiver, Generic[TOptionsValidator], ABC): ytdl options to enable/disable when downloading entries for this specific plugin """ - def split(self, entry: Entry) -> List[Tuple[Entry, FileMetadata]]: - """ - Very specialized function that takes an entry and creates multiple entries from it. - Should mark ``is_split_plugin`` on the plugin class. - - Parameters - ---------- - entry - Entry to create multiple entries from - - Returns - ------- - List of entries and metadata created from the source entry - """ - return [] - def modify_entry_metadata(self, entry: Entry) -> Optional[Entry]: """ After entry metadata has been gathered, perform preprocessing on the metadata @@ -135,9 +122,30 @@ class Plugin(DownloadArchiver, Generic[TOptionsValidator], ABC): """ return None - # pylint: enable=no-self-use,unused-argument - def post_process_subscription(self): """ After all downloaded files have been post-processed, apply a subscription-wide post process """ + + +class SplitPlugin(Plugin[TOptionsValidator], Generic[TOptionsValidator], ABC): + """ + Plugin that splits entries into zero or more entries + """ + + @abstractmethod + def split(self, entry: Entry) -> List[Tuple[Entry, FileMetadata]]: + """ + Very specialized function that takes an entry and creates multiple entries from it. + Should mark ``is_split_plugin`` on the plugin class. + + Parameters + ---------- + entry + Entry to create multiple entries from + + Returns + ------- + List of entries and metadata created from the source entry + """ + return [] diff --git a/src/ytdl_sub/config/preset.py b/src/ytdl_sub/config/preset.py index 45b4db69..4cac9d71 100644 --- a/src/ytdl_sub/config/preset.py +++ b/src/ytdl_sub/config/preset.py @@ -11,6 +11,7 @@ from typing import Union from mergedeep import mergedeep from ytdl_sub.config.config_validator import ConfigValidator +from ytdl_sub.config.plugin import Plugin 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 @@ -21,7 +22,6 @@ from ytdl_sub.config.preset_options import YTDLOptions from ytdl_sub.downloaders.base_downloader import BaseDownloader from ytdl_sub.downloaders.downloader_validator import DownloaderValidator from ytdl_sub.entries.entry import Entry -from ytdl_sub.plugins.plugin import Plugin from ytdl_sub.prebuilt_presets import PREBUILT_PRESET_NAMES from ytdl_sub.prebuilt_presets import PUBLISHED_PRESET_NAMES from ytdl_sub.utils.exceptions import ValidationException diff --git a/src/ytdl_sub/config/preset_class_mappings.py b/src/ytdl_sub/config/preset_class_mappings.py index a77e4988..ee5fe43c 100644 --- a/src/ytdl_sub/config/preset_class_mappings.py +++ b/src/ytdl_sub/config/preset_class_mappings.py @@ -2,6 +2,7 @@ from typing import Dict from typing import List from typing import Type +from ytdl_sub.config.plugin import Plugin from ytdl_sub.downloaders.base_downloader import BaseDownloader from ytdl_sub.downloaders.url.multi_url import MultiUrlDownloader from ytdl_sub.downloaders.url.url import UrlDownloader @@ -15,7 +16,6 @@ from ytdl_sub.plugins.match_filters import MatchFiltersPlugin from ytdl_sub.plugins.music_tags import MusicTagsPlugin from ytdl_sub.plugins.nfo_tags import NfoTagsPlugin from ytdl_sub.plugins.output_directory_nfo_tags import OutputDirectoryNfoTagsPlugin -from ytdl_sub.plugins.plugin import Plugin from ytdl_sub.plugins.regex import RegexPlugin from ytdl_sub.plugins.split_by_chapters import SplitByChaptersPlugin from ytdl_sub.plugins.subtitles import SubtitlesPlugin diff --git a/src/ytdl_sub/downloaders/base_downloader.py b/src/ytdl_sub/downloaders/base_downloader.py index b0c5f367..3976ccb4 100644 --- a/src/ytdl_sub/downloaders/base_downloader.py +++ b/src/ytdl_sub/downloaders/base_downloader.py @@ -5,12 +5,12 @@ from typing import Iterable from typing import List from typing import Type +from ytdl_sub.config.plugin import Plugin from ytdl_sub.config.preset_options import Overrides from ytdl_sub.config.preset_options import TOptionsValidator from ytdl_sub.downloaders.downloader_validator import TDownloaderValidator 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.ytdl_additions.enhanced_download_archive import DownloadArchiver from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive @@ -29,7 +29,7 @@ class BaseDownloaderPlugin(Plugin[TDownloaderValidator], ABC): ): super().__init__( # Downloader plugins use download options as their plugin options - plugin_options=downloader_options, + options=downloader_options, overrides=overrides, enhanced_download_archive=enhanced_download_archive, ) diff --git a/src/ytdl_sub/downloaders/url/downloader.py b/src/ytdl_sub/downloaders/url/downloader.py index 1828e626..7a7b4425 100644 --- a/src/ytdl_sub/downloaders/url/downloader.py +++ b/src/ytdl_sub/downloaders/url/downloader.py @@ -12,6 +12,7 @@ from typing import Tuple from yt_dlp.utils import RejectedVideoReached +from ytdl_sub.config.plugin import Plugin from ytdl_sub.config.preset_options import Overrides from ytdl_sub.downloaders.base_downloader import BaseDownloader from ytdl_sub.downloaders.base_downloader import BaseDownloaderPlugin @@ -33,7 +34,6 @@ from ytdl_sub.entries.variables.kwargs import SOURCE_ENTRY from ytdl_sub.entries.variables.kwargs import SPONSORBLOCK_CHAPTERS from ytdl_sub.entries.variables.kwargs import UPLOAD_DATE_INDEX from ytdl_sub.entries.variables.kwargs import YTDL_SUB_MATCH_FILTER_REJECT -from ytdl_sub.plugins.plugin import Plugin from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.logger import Logger from ytdl_sub.utils.thumbnail import ThumbnailTypes diff --git a/src/ytdl_sub/plugins/audio_extract.py b/src/ytdl_sub/plugins/audio_extract.py index de4b2058..7418a146 100644 --- a/src/ytdl_sub/plugins/audio_extract.py +++ b/src/ytdl_sub/plugins/audio_extract.py @@ -3,10 +3,10 @@ from typing import Any from typing import Dict from typing import Optional +from ytdl_sub.config.plugin import Plugin 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.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 diff --git a/src/ytdl_sub/plugins/chapters.py b/src/ytdl_sub/plugins/chapters.py index 03928f68..456994f5 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.plugin import Plugin 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.utils.chapters import Chapters from ytdl_sub.utils.ffmpeg import set_ffmpeg_metadata_chapters from ytdl_sub.utils.file_handler import FileMetadata diff --git a/src/ytdl_sub/plugins/date_range.py b/src/ytdl_sub/plugins/date_range.py index fb18d892..3ad3932b 100644 --- a/src/ytdl_sub/plugins/date_range.py +++ b/src/ytdl_sub/plugins/date_range.py @@ -1,9 +1,9 @@ from typing import Dict from typing import Optional +from ytdl_sub.config.plugin import Plugin 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.utils.datetime import to_date_range from ytdl_sub.validators.string_datetime import StringDatetimeValidator diff --git a/src/ytdl_sub/plugins/embed_thumbnail.py b/src/ytdl_sub/plugins/embed_thumbnail.py index fac7e050..45dbd776 100644 --- a/src/ytdl_sub/plugins/embed_thumbnail.py +++ b/src/ytdl_sub/plugins/embed_thumbnail.py @@ -3,10 +3,10 @@ from typing import Optional import mediafile +from ytdl_sub.config.plugin import Plugin +from ytdl_sub.config.plugin import PluginPriority from ytdl_sub.config.preset_options import OptionsValidator from ytdl_sub.entries.entry import Entry -from ytdl_sub.plugins.plugin import Plugin -from ytdl_sub.plugins.plugin import PluginPriority from ytdl_sub.utils.ffmpeg import FFMPEG from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileMetadata diff --git a/src/ytdl_sub/plugins/file_convert.py b/src/ytdl_sub/plugins/file_convert.py index 86c4a303..8d2e1cd0 100644 --- a/src/ytdl_sub/plugins/file_convert.py +++ b/src/ytdl_sub/plugins/file_convert.py @@ -3,11 +3,11 @@ from typing import Any from typing import Dict from typing import Optional +from ytdl_sub.config.plugin import Plugin +from ytdl_sub.config.plugin import PluginPriority 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 PluginPriority from ytdl_sub.utils.exceptions import FileNotDownloadedException from ytdl_sub.utils.exceptions import ValidationException from ytdl_sub.utils.ffmpeg import FFMPEG diff --git a/src/ytdl_sub/plugins/internal/view.py b/src/ytdl_sub/plugins/internal/view.py index ff7946f7..fa8d5471 100644 --- a/src/ytdl_sub/plugins/internal/view.py +++ b/src/ytdl_sub/plugins/internal/view.py @@ -1,12 +1,11 @@ import copy from typing import Optional +from ytdl_sub.config.plugin import Plugin +from ytdl_sub.config.plugin import PluginPriority 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 PluginPriority from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive @@ -27,11 +26,15 @@ class ViewPlugin(Plugin[ViewOptions]): def __init__( self, - plugin_options: OutputDirectoryNfoTagsOptions, + options: ViewOptions, overrides: Overrides, enhanced_download_archive: EnhancedDownloadArchive, ): - super().__init__(plugin_options, overrides, enhanced_download_archive) + super().__init__( + options=options, + overrides=overrides, + enhanced_download_archive=enhanced_download_archive, + ) self._first_entry: Optional[Entry] = None @classmethod diff --git a/src/ytdl_sub/plugins/match_filters.py b/src/ytdl_sub/plugins/match_filters.py index 8dd3ce5c..dda5f370 100644 --- a/src/ytdl_sub/plugins/match_filters.py +++ b/src/ytdl_sub/plugins/match_filters.py @@ -5,11 +5,11 @@ from typing import Optional from yt_dlp import match_filter_func +from ytdl_sub.config.plugin import Plugin +from ytdl_sub.config.plugin import PluginPriority 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 PluginPriority from ytdl_sub.utils.logger import Logger from ytdl_sub.validators.validators import StringListValidator diff --git a/src/ytdl_sub/plugins/music_tags.py b/src/ytdl_sub/plugins/music_tags.py index 43974492..7dcbfdaa 100644 --- a/src/ytdl_sub/plugins/music_tags.py +++ b/src/ytdl_sub/plugins/music_tags.py @@ -6,9 +6,9 @@ from typing import List import mediafile +from ytdl_sub.config.plugin import Plugin 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.utils.file_handler import FileMetadata from ytdl_sub.utils.logger import Logger from ytdl_sub.utils.thumbnail import convert_download_thumbnail diff --git a/src/ytdl_sub/plugins/nfo_tags.py b/src/ytdl_sub/plugins/nfo_tags.py index d76bf5c6..f9b3cc33 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.plugin import Plugin 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.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.utils.xml import XmlElement diff --git a/src/ytdl_sub/plugins/output_directory_nfo_tags.py b/src/ytdl_sub/plugins/output_directory_nfo_tags.py index cc050a6e..d1e23ab1 100644 --- a/src/ytdl_sub/plugins/output_directory_nfo_tags.py +++ b/src/ytdl_sub/plugins/output_directory_nfo_tags.py @@ -93,11 +93,11 @@ class OutputDirectoryNfoTagsPlugin(SharedNfoTagsPlugin): def __init__( self, - plugin_options: OutputDirectoryNfoTagsOptions, + options: OutputDirectoryNfoTagsOptions, overrides: Overrides, enhanced_download_archive: EnhancedDownloadArchive, ): - super().__init__(plugin_options, overrides, enhanced_download_archive) + super().__init__(options, overrides, enhanced_download_archive) self._last_entry: Optional[Entry] = None def post_process_entry(self, entry: Entry) -> None: diff --git a/src/ytdl_sub/plugins/regex.py b/src/ytdl_sub/plugins/regex.py index fcafd258..29fe58be 100644 --- a/src/ytdl_sub/plugins/regex.py +++ b/src/ytdl_sub/plugins/regex.py @@ -5,11 +5,11 @@ from typing import Optional from yt_dlp.utils import sanitize_filename +from ytdl_sub.config.plugin import Plugin +from ytdl_sub.config.plugin import PluginPriority 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 PluginPriority from ytdl_sub.utils.exceptions import RegexNoMatchException from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException from ytdl_sub.utils.logger import Logger diff --git a/src/ytdl_sub/plugins/split_by_chapters.py b/src/ytdl_sub/plugins/split_by_chapters.py index 63fbb11f..f684f921 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.plugin import SplitPlugin 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.utils.chapters import Chapters from ytdl_sub.utils.chapters import Timestamp from ytdl_sub.utils.exceptions import ValidationException @@ -101,9 +101,8 @@ class SplitByChaptersOptions(OptionsDictValidator): return self._when_no_chapters -class SplitByChaptersPlugin(Plugin[SplitByChaptersOptions]): +class SplitByChaptersPlugin(SplitPlugin[SplitByChaptersOptions]): plugin_options_type = SplitByChaptersOptions - is_split_plugin = True def _create_split_entry( self, source_entry: Entry, title: str, idx: int, chapters: Chapters diff --git a/src/ytdl_sub/plugins/subtitles.py b/src/ytdl_sub/plugins/subtitles.py index 03097863..4dff539d 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.plugin import Plugin 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.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.utils.logger import Logger diff --git a/src/ytdl_sub/plugins/video_tags.py b/src/ytdl_sub/plugins/video_tags.py index 02601f3b..e27af4d8 100644 --- a/src/ytdl_sub/plugins/video_tags.py +++ b/src/ytdl_sub/plugins/video_tags.py @@ -2,9 +2,9 @@ import copy from typing import Any from typing import Dict +from ytdl_sub.config.plugin import Plugin 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.utils.ffmpeg import add_ffmpeg_metadata_key_values from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.utils.logger import Logger diff --git a/src/ytdl_sub/subscriptions/subscription_download.py b/src/ytdl_sub/subscriptions/subscription_download.py index 92ca121b..7234a3df 100644 --- a/src/ytdl_sub/subscriptions/subscription_download.py +++ b/src/ytdl_sub/subscriptions/subscription_download.py @@ -6,12 +6,13 @@ from pathlib import Path from typing import List from typing import Optional +from ytdl_sub.config.plugin import Plugin +from ytdl_sub.config.plugin import SplitPlugin from ytdl_sub.downloaders.base_downloader import BaseDownloader from ytdl_sub.downloaders.info_json.info_json_downloader import InfoJsonDownloader from ytdl_sub.downloaders.info_json.info_json_downloader import InfoJsonDownloaderOptions 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.subscriptions.base_subscription import BaseSubscription from ytdl_sub.subscriptions.subscription_ytdl_options import SubscriptionYTDLOptions from ytdl_sub.utils.datetime import to_date_range @@ -22,8 +23,8 @@ from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.utils.thumbnail import convert_download_thumbnail -def _get_split_plugin(plugins: List[Plugin]) -> Optional[Plugin]: - split_plugins = [plugin for plugin in plugins if plugin.is_split_plugin] +def _get_split_plugin(plugins: List[Plugin]) -> Optional[SplitPlugin]: + split_plugins = [plugin for plugin in plugins if isinstance(plugin, SplitPlugin)] if len(split_plugins) == 1: return split_plugins[0] @@ -182,7 +183,7 @@ class SubscriptionDownload(BaseSubscription, ABC): for plugin_type, plugin_options in self.plugins.zipped(): plugin = plugin_type( - plugin_options=plugin_options, + options=plugin_options, overrides=self.overrides, enhanced_download_archive=self._enhanced_download_archive, ) @@ -243,7 +244,7 @@ class SubscriptionDownload(BaseSubscription, ABC): self._cleanup_entry_files(entry) def _process_split_entry( - self, split_plugin: Plugin, plugins: List[Plugin], dry_run: bool, entry: Entry + self, split_plugin: SplitPlugin, plugins: List[Plugin], dry_run: bool, entry: Entry ) -> None: entry_: Optional[Entry] = entry diff --git a/src/ytdl_sub/subscriptions/subscription_ytdl_options.py b/src/ytdl_sub/subscriptions/subscription_ytdl_options.py index c108033e..ee873a4e 100644 --- a/src/ytdl_sub/subscriptions/subscription_ytdl_options.py +++ b/src/ytdl_sub/subscriptions/subscription_ytdl_options.py @@ -5,6 +5,7 @@ from typing import Optional from typing import Type from typing import TypeVar +from ytdl_sub.config.plugin import Plugin from ytdl_sub.config.preset import Preset from ytdl_sub.downloaders.base_downloader import BaseDownloader from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder @@ -13,7 +14,6 @@ from ytdl_sub.plugins.chapters import ChaptersPlugin from ytdl_sub.plugins.date_range import DateRangePlugin from ytdl_sub.plugins.file_convert import FileConvertPlugin from ytdl_sub.plugins.match_filters import MatchFiltersPlugin -from ytdl_sub.plugins.plugin import Plugin from ytdl_sub.plugins.subtitles import SubtitlesPlugin from ytdl_sub.utils.ffmpeg import FFMPEG from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive