diff --git a/src/ytdl_sub/config/preset.py b/src/ytdl_sub/config/preset.py index 4cac9d71..fdedfdb9 100644 --- a/src/ytdl_sub/config/preset.py +++ b/src/ytdl_sub/config/preset.py @@ -19,8 +19,7 @@ from ytdl_sub.config.preset_options import OutputOptions from ytdl_sub.config.preset_options import Overrides from ytdl_sub.config.preset_options import TOptionsValidator 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.downloaders.source_plugin import SourcePlugin from ytdl_sub.entries.entry import Entry from ytdl_sub.prebuilt_presets import PREBUILT_PRESET_NAMES from ytdl_sub.prebuilt_presets import PUBLISHED_PRESET_NAMES @@ -121,7 +120,7 @@ class DownloadStrategyValidator(StrictDictValidator): validator=StringValidator, ).value - def get(self, downloader_source: str) -> Type[BaseDownloader]: + def get(self, downloader_source: str) -> Type[SourcePlugin]: """ Parameters ---------- @@ -213,7 +212,7 @@ class Preset(_PresetShell): ) del source_dict["download_strategy"] - downloader.downloader_options_type.partial_validate( + downloader.plugin_options_type.partial_validate( name=f"{name}.{source_name}", value=source_dict ) @@ -270,26 +269,24 @@ class Preset(_PresetShell): def _source_variables(self) -> List[str]: return Entry.source_variables() - def __validate_and_get_downloader(self, downloader_source: str) -> Type[BaseDownloader]: + def __validate_and_get_downloader(self, downloader_source: str) -> Type[SourcePlugin]: return self._validate_key(key=downloader_source, validator=DownloadStrategyValidator).get( downloader_source=downloader_source ) def __validate_and_get_downloader_options( - self, downloader_source: str, downloader: Type[BaseDownloader] - ) -> DownloaderValidator: + self, downloader_source: str, downloader: Type[SourcePlugin] + ) -> OptionsValidator: # Remove the download_strategy key before validating it against the downloader options # TODO: make this cleaner del self._dict[downloader_source]["download_strategy"] - return self._validate_key( - key=downloader_source, validator=downloader.downloader_options_type - ) + return self._validate_key(key=downloader_source, validator=downloader.plugin_options_type) def __validate_and_get_downloader_and_options( self, - ) -> Tuple[Type[BaseDownloader], DownloaderValidator]: - downloader: Optional[Type[BaseDownloader]] = None - download_options: Optional[DownloaderValidator] = None + ) -> Tuple[Type[SourcePlugin], OptionsValidator]: + downloader: Optional[Type[SourcePlugin]] = None + download_options: Optional[OptionsValidator] = None downloader_sources = DownloadStrategyMapping.sources() for key in self._keys: diff --git a/src/ytdl_sub/config/preset_class_mappings.py b/src/ytdl_sub/config/preset_class_mappings.py index ee5fe43c..5ab2f7c2 100644 --- a/src/ytdl_sub/config/preset_class_mappings.py +++ b/src/ytdl_sub/config/preset_class_mappings.py @@ -3,7 +3,7 @@ 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.source_plugin import SourcePlugin from ytdl_sub.downloaders.url.multi_url import MultiUrlDownloader from ytdl_sub.downloaders.url.url import UrlDownloader from ytdl_sub.plugins.audio_extract import AudioExtractPlugin @@ -27,7 +27,7 @@ class DownloadStrategyMapping: Maps downloader strategies defined in the preset to its respective downloader class """ - _MAPPING: Dict[str, Dict[str, Type[BaseDownloader]]] = { + _MAPPING: Dict[str, Dict[str, Type[SourcePlugin]]] = { "download": { "multi_url": MultiUrlDownloader, "url": UrlDownloader, @@ -82,7 +82,7 @@ class DownloadStrategyMapping: ) @classmethod - def get(cls, source: str, download_strategy: str) -> Type[BaseDownloader]: + def get(cls, source: str, download_strategy: str) -> Type[SourcePlugin]: """ Parameters ---------- diff --git a/src/ytdl_sub/downloaders/info_json/info_json_downloader.py b/src/ytdl_sub/downloaders/info_json/info_json_downloader.py index d2facc3b..f0c37083 100644 --- a/src/ytdl_sub/downloaders/info_json/info_json_downloader.py +++ b/src/ytdl_sub/downloaders/info_json/info_json_downloader.py @@ -7,7 +7,7 @@ from typing import List from ytdl_sub.config.preset_options import OptionsDictValidator from ytdl_sub.config.preset_options import Overrides -from ytdl_sub.downloaders.base_downloader import BaseDownloader +from ytdl_sub.downloaders.source_plugin import SourcePlugin from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder from ytdl_sub.entries.entry import Entry from ytdl_sub.utils.exceptions import ValidationException @@ -21,19 +21,19 @@ class InfoJsonDownloaderOptions(OptionsDictValidator): _optional_keys = {"no-op"} -class InfoJsonDownloader(BaseDownloader[InfoJsonDownloaderOptions]): - downloader_options_type = InfoJsonDownloaderOptions +class InfoJsonDownloader(SourcePlugin[InfoJsonDownloaderOptions]): + plugin_options_type = InfoJsonDownloaderOptions def __init__( self, - download_options: InfoJsonDownloaderOptions, + options: InfoJsonDownloaderOptions, enhanced_download_archive: EnhancedDownloadArchive, download_ytdl_options: YTDLOptionsBuilder, metadata_ytdl_options: YTDLOptionsBuilder, overrides: Overrides, ): super().__init__( - download_options=download_options, + options=options, enhanced_download_archive=enhanced_download_archive, download_ytdl_options=download_ytdl_options, metadata_ytdl_options=metadata_ytdl_options, diff --git a/src/ytdl_sub/downloaders/base_downloader.py b/src/ytdl_sub/downloaders/source_plugin.py similarity index 65% rename from src/ytdl_sub/downloaders/base_downloader.py rename to src/ytdl_sub/downloaders/source_plugin.py index 3976ccb4..f10ae796 100644 --- a/src/ytdl_sub/downloaders/base_downloader.py +++ b/src/ytdl_sub/downloaders/source_plugin.py @@ -3,52 +3,37 @@ from abc import ABC from typing import Generic from typing import Iterable from typing import List -from typing import Type +from ytdl_sub.config.plugin import BasePlugin 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.ytdl_additions.enhanced_download_archive import DownloadArchiver from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive -class BaseDownloaderPlugin(Plugin[TDownloaderValidator], ABC): +class SourcePluginExtension(Plugin[TOptionsValidator], ABC): """ Plugins that get added automatically by using a downloader. Downloader options are the plugin options. """ + +class SourcePlugin(BasePlugin[TOptionsValidator], Generic[TOptionsValidator], ABC): def __init__( self, - downloader_options: TDownloaderValidator, - overrides: Overrides, - enhanced_download_archive: EnhancedDownloadArchive, - ): - super().__init__( - # Downloader plugins use download options as their plugin options - options=downloader_options, - overrides=overrides, - enhanced_download_archive=enhanced_download_archive, - ) - - -class BaseDownloader(DownloadArchiver, Generic[TOptionsValidator], ABC): - downloader_options_type: Type[TOptionsValidator] - - def __init__( - self, - download_options: TOptionsValidator, + options: TOptionsValidator, enhanced_download_archive: EnhancedDownloadArchive, download_ytdl_options: YTDLOptionsBuilder, metadata_ytdl_options: YTDLOptionsBuilder, overrides: Overrides, ): - super().__init__(enhanced_download_archive=enhanced_download_archive) - self.download_options = download_options - self.overrides = overrides + super().__init__( + options=options, + overrides=overrides, + enhanced_download_archive=enhanced_download_archive, + ) self._download_ytdl_options_builder = download_ytdl_options self._metadata_ytdl_options_builder = metadata_ytdl_options @@ -67,7 +52,7 @@ class BaseDownloader(DownloadArchiver, Generic[TOptionsValidator], ABC): downloader_options: TOptionsValidator, enhanced_download_archive: EnhancedDownloadArchive, overrides: Overrides, - ) -> List[BaseDownloaderPlugin]: + ) -> List[SourcePluginExtension]: """Add these plugins from the Downloader to the subscription""" return [] diff --git a/src/ytdl_sub/downloaders/url/downloader.py b/src/ytdl_sub/downloaders/url/downloader.py index 7a7b4425..f8023d32 100644 --- a/src/ytdl_sub/downloaders/url/downloader.py +++ b/src/ytdl_sub/downloaders/url/downloader.py @@ -14,10 +14,14 @@ 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 -from ytdl_sub.downloaders.downloader_validator import DownloaderValidator -from ytdl_sub.downloaders.downloader_validator import TDownloaderValidator +from ytdl_sub.downloaders.source_plugin import SourcePlugin +from ytdl_sub.downloaders.source_plugin import SourcePluginExtension +from ytdl_sub.downloaders.url.multi_url_source_options_validator import ( + MultiUrlSourceOptionsValidator, +) +from ytdl_sub.downloaders.url.multi_url_source_options_validator import ( + TMultiURLSourceOptionsValidator, +) from ytdl_sub.downloaders.url.validators import MultiUrlValidator from ytdl_sub.downloaders.url.validators import UrlThumbnailListValidator from ytdl_sub.downloaders.url.validators import UrlValidator @@ -50,22 +54,22 @@ class URLDownloadState: self.entries_downloaded = 0 -class UrlDownloaderThumbnailPlugin(BaseDownloaderPlugin): +class UrlDownloaderThumbnailPlugin(SourcePluginExtension): def __init__( self, - downloader_options: DownloaderValidator, + options: MultiUrlSourceOptionsValidator, overrides: Overrides, enhanced_download_archive: EnhancedDownloadArchive, ): super().__init__( - downloader_options=downloader_options, + options=options, overrides=overrides, enhanced_download_archive=enhanced_download_archive, ) self._thumbnails_downloaded: Set[str] = set() self._collection_url_mapping: Dict[str, UrlValidator] = { self.overrides.apply_formatter(collection_url.url): collection_url - for collection_url in downloader_options.collection_validator.urls.list + for collection_url in options.collection_validator.urls.list } def _download_parent_thumbnails( @@ -149,15 +153,15 @@ class UrlDownloaderThumbnailPlugin(BaseDownloaderPlugin): return entry -class UrlDownloaderCollectionVariablePlugin(BaseDownloaderPlugin): +class UrlDownloaderCollectionVariablePlugin(SourcePluginExtension): def __init__( self, - downloader_options: DownloaderValidator, + downloader_options: MultiUrlSourceOptionsValidator, overrides: Overrides, enhanced_download_archive: EnhancedDownloadArchive, ): super().__init__( - downloader_options=downloader_options, + options=downloader_options, overrides=overrides, enhanced_download_archive=enhanced_download_archive, ) @@ -186,7 +190,7 @@ class UrlDownloaderCollectionVariablePlugin(BaseDownloaderPlugin): return entry -class BaseUrlDownloader(BaseDownloader[TDownloaderValidator], ABC): +class BaseUrlDownloader(SourcePlugin[TMultiURLSourceOptionsValidator], ABC): """ Class that interacts with ytdl to perform the download of metadata and content, and should translate that to list of Entry objects. @@ -195,7 +199,7 @@ class BaseUrlDownloader(BaseDownloader[TDownloaderValidator], ABC): @classmethod def added_plugins( cls, - downloader_options: TDownloaderValidator, + downloader_options: TMultiURLSourceOptionsValidator, enhanced_download_archive: EnhancedDownloadArchive, overrides: Overrides, ) -> List[Plugin]: @@ -206,7 +210,7 @@ class BaseUrlDownloader(BaseDownloader[TDownloaderValidator], ABC): """ return [ UrlDownloaderThumbnailPlugin( - downloader_options=downloader_options, + options=downloader_options, overrides=overrides, enhanced_download_archive=enhanced_download_archive, ), @@ -229,7 +233,7 @@ class BaseUrlDownloader(BaseDownloader[TDownloaderValidator], ABC): def __init__( self, - download_options: TDownloaderValidator, + options: TMultiURLSourceOptionsValidator, enhanced_download_archive: EnhancedDownloadArchive, download_ytdl_options: YTDLOptionsBuilder, metadata_ytdl_options: YTDLOptionsBuilder, @@ -238,7 +242,7 @@ class BaseUrlDownloader(BaseDownloader[TDownloaderValidator], ABC): """ Parameters ---------- - download_options + options Options validator for this downloader enhanced_download_archive Download archive @@ -250,7 +254,7 @@ class BaseUrlDownloader(BaseDownloader[TDownloaderValidator], ABC): Override variables """ super().__init__( - download_options=download_options, + options=options, enhanced_download_archive=enhanced_download_archive, download_ytdl_options=download_ytdl_options, metadata_ytdl_options=metadata_ytdl_options, @@ -315,7 +319,7 @@ class BaseUrlDownloader(BaseDownloader[TDownloaderValidator], ABC): @property def collection(self) -> MultiUrlValidator: """Return the download options collection""" - return self.download_options.collection_validator + return self.plugin_options.collection_validator @contextlib.contextmanager def _separate_download_archives(self, clear_info_json_files: bool = False): diff --git a/src/ytdl_sub/downloaders/url/multi_url.py b/src/ytdl_sub/downloaders/url/multi_url.py index 822bd0ed..40c2d5d3 100644 --- a/src/ytdl_sub/downloaders/url/multi_url.py +++ b/src/ytdl_sub/downloaders/url/multi_url.py @@ -1,12 +1,14 @@ from typing import Dict from typing import List -from ytdl_sub.downloaders.downloader_validator import DownloaderValidator from ytdl_sub.downloaders.url.downloader import BaseUrlDownloader +from ytdl_sub.downloaders.url.multi_url_source_options_validator import ( + MultiUrlSourceOptionsValidator, +) from ytdl_sub.downloaders.url.validators import MultiUrlValidator -class MultiUrlDownloadOptions(MultiUrlValidator, DownloaderValidator): +class MultiUrlDownloadOptions(MultiUrlValidator, MultiUrlSourceOptionsValidator): """ Downloads from multiple URLs. If an entry is returned from more than one URL, it will resolve to the bottom-most URL settings. @@ -65,4 +67,4 @@ class MultiUrlDownloadOptions(MultiUrlValidator, DownloaderValidator): class MultiUrlDownloader(BaseUrlDownloader[MultiUrlDownloadOptions]): - downloader_options_type = MultiUrlDownloadOptions + plugin_options_type = MultiUrlDownloadOptions diff --git a/src/ytdl_sub/downloaders/downloader_validator.py b/src/ytdl_sub/downloaders/url/multi_url_source_options_validator.py similarity index 86% rename from src/ytdl_sub/downloaders/downloader_validator.py rename to src/ytdl_sub/downloaders/url/multi_url_source_options_validator.py index a88bb0bd..4ccedf54 100644 --- a/src/ytdl_sub/downloaders/downloader_validator.py +++ b/src/ytdl_sub/downloaders/url/multi_url_source_options_validator.py @@ -8,7 +8,7 @@ from ytdl_sub.config.preset_options import OptionsValidator from ytdl_sub.downloaders.url.validators import MultiUrlValidator -class DownloaderValidator(OptionsValidator, ABC): +class MultiUrlSourceOptionsValidator(OptionsValidator, ABC): """ Placeholder class to define downloader options """ @@ -42,4 +42,6 @@ class DownloaderValidator(OptionsValidator, ABC): ) -TDownloaderValidator = TypeVar("TDownloaderValidator", bound=DownloaderValidator) +TMultiURLSourceOptionsValidator = TypeVar( + "TMultiURLSourceOptionsValidator", bound=MultiUrlSourceOptionsValidator +) diff --git a/src/ytdl_sub/downloaders/url/url.py b/src/ytdl_sub/downloaders/url/url.py index 9d8df650..cd79c430 100644 --- a/src/ytdl_sub/downloaders/url/url.py +++ b/src/ytdl_sub/downloaders/url/url.py @@ -1,10 +1,12 @@ -from ytdl_sub.downloaders.downloader_validator import DownloaderValidator from ytdl_sub.downloaders.url.downloader import BaseUrlDownloader +from ytdl_sub.downloaders.url.multi_url_source_options_validator import ( + MultiUrlSourceOptionsValidator, +) from ytdl_sub.downloaders.url.validators import MultiUrlValidator from ytdl_sub.downloaders.url.validators import UrlValidator -class UrlDownloadOptions(UrlValidator, DownloaderValidator): +class UrlDownloadOptions(UrlValidator, MultiUrlSourceOptionsValidator): """ Downloads from a single URL supported by yt-dlp. @@ -37,4 +39,4 @@ class UrlDownloadOptions(UrlValidator, DownloaderValidator): class UrlDownloader(BaseUrlDownloader[UrlDownloadOptions]): - downloader_options_type = UrlDownloadOptions + plugin_options_type = UrlDownloadOptions diff --git a/src/ytdl_sub/subscriptions/base_subscription.py b/src/ytdl_sub/subscriptions/base_subscription.py index 14dbb9fc..82c697b5 100644 --- a/src/ytdl_sub/subscriptions/base_subscription.py +++ b/src/ytdl_sub/subscriptions/base_subscription.py @@ -5,11 +5,11 @@ from typing import Type from ytdl_sub.config.config_validator import ConfigOptions from ytdl_sub.config.preset import Preset from ytdl_sub.config.preset import PresetPlugins +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 -from ytdl_sub.downloaders.base_downloader import BaseDownloader -from ytdl_sub.downloaders.downloader_validator import DownloaderValidator +from ytdl_sub.downloaders.source_plugin import SourcePlugin from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive @@ -52,7 +52,7 @@ class BaseSubscription(ABC): ) @property - def downloader_class(self) -> Type[BaseDownloader]: + def downloader_class(self) -> Type[SourcePlugin]: """ Returns ------- @@ -61,7 +61,7 @@ class BaseSubscription(ABC): return self._preset_options.downloader @property - def downloader_options(self) -> DownloaderValidator: + def downloader_options(self) -> OptionsValidator: """ Returns ------- diff --git a/src/ytdl_sub/subscriptions/subscription_download.py b/src/ytdl_sub/subscriptions/subscription_download.py index 7234a3df..528c7959 100644 --- a/src/ytdl_sub/subscriptions/subscription_download.py +++ b/src/ytdl_sub/subscriptions/subscription_download.py @@ -8,9 +8,9 @@ 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.source_plugin import SourcePlugin from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder from ytdl_sub.entries.entry import Entry from ytdl_sub.subscriptions.base_subscription import BaseSubscription @@ -291,7 +291,7 @@ class SubscriptionDownload(BaseSubscription, ABC): def _process_subscription( self, plugins: List[Plugin], - downloader: BaseDownloader, + downloader: SourcePlugin, dry_run: bool, ) -> FileHandlerTransactionLog: with self._subscription_download_context_managers(): @@ -340,7 +340,7 @@ class SubscriptionDownload(BaseSubscription, ABC): ) downloader = self.downloader_class( - download_options=self.downloader_options, + options=self.downloader_options, enhanced_download_archive=self._enhanced_download_archive, download_ytdl_options=subscription_ytdl_options.download_builder(), metadata_ytdl_options=subscription_ytdl_options.metadata_builder(), @@ -366,7 +366,7 @@ class SubscriptionDownload(BaseSubscription, ABC): plugins = self._initialize_plugins() downloader = InfoJsonDownloader( - download_options=InfoJsonDownloaderOptions(name="no-op", value={}), + options=InfoJsonDownloaderOptions(name="no-op", value={}), enhanced_download_archive=self._enhanced_download_archive, download_ytdl_options=YTDLOptionsBuilder(), metadata_ytdl_options=YTDLOptionsBuilder(), diff --git a/src/ytdl_sub/subscriptions/subscription_ytdl_options.py b/src/ytdl_sub/subscriptions/subscription_ytdl_options.py index ee873a4e..b4bdeb3e 100644 --- a/src/ytdl_sub/subscriptions/subscription_ytdl_options.py +++ b/src/ytdl_sub/subscriptions/subscription_ytdl_options.py @@ -7,7 +7,7 @@ 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.source_plugin import SourcePlugin from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder from ytdl_sub.plugins.audio_extract import AudioExtractPlugin from ytdl_sub.plugins.chapters import ChaptersPlugin @@ -43,7 +43,7 @@ class SubscriptionYTDLOptions: return None @property - def _downloader(self) -> Type[BaseDownloader]: + def _downloader(self) -> Type[SourcePlugin]: return self._preset.downloader @property