generics are dope

This commit is contained in:
jbannon 2022-04-06 22:28:27 +00:00
parent 85b14214ee
commit 4b05a13714
3 changed files with 30 additions and 77 deletions

View file

@ -1,4 +1,3 @@
from abc import ABC
from typing import List from typing import List
from ytdl_subscribe.downloaders.soundcloud_downloader import SoundcloudDownloader from ytdl_subscribe.downloaders.soundcloud_downloader import SoundcloudDownloader
@ -13,32 +12,16 @@ from ytdl_subscribe.validators.config.source_options.soundcloud_validators impor
) )
class SoundcloudSubscription(Subscription, ABC): class SoundcloudAlbumsAndSinglesSubscription(
source_validator_type = SoundcloudSourceValidator Subscription[SoundcloudSourceValidator, SoundcloudAlbumsAndSinglesDownloadValidator]
downloader_type = SoundcloudDownloader ):
@property
def source_options(self) -> SoundcloudSourceValidator:
return super().source_options
@property
def downloader(self) -> SoundcloudDownloader:
return super().downloader
class SoundcloudAlbumsAndSinglesSubscription(SoundcloudSubscription):
download_strategy_type = SoundcloudAlbumsAndSinglesDownloadValidator
@property
def download_strategy_options(self) -> SoundcloudAlbumsAndSinglesDownloadValidator:
return super().download_strategy_options
def extract_info(self): def extract_info(self):
tracks: List[SoundcloudTrack] = [] tracks: List[SoundcloudTrack] = []
downloader = self.get_downloader(SoundcloudDownloader)
# Get the album info first. This tells us which track ids belong # Get the album info first. This tells us which track ids belong
# to an album. Unfortunately we cannot use download_archive or info.json for this # to an album. Unfortunately we cannot use download_archive or info.json for this
albums: List[SoundcloudAlbum] = self.downloader.download_albums( albums: List[SoundcloudAlbum] = downloader.download_albums(
artist_name=self.download_strategy_options.username.value artist_name=self.download_strategy_options.username.value
) )
@ -48,7 +31,7 @@ class SoundcloudAlbumsAndSinglesSubscription(SoundcloudSubscription):
) )
# only add tracks that are not part of an album # only add tracks that are not part of an album
single_tracks = self.downloader.download_tracks( single_tracks = downloader.download_tracks(
artist_name=self.download_strategy_options.username.value artist_name=self.download_strategy_options.username.value
) )
tracks += [ tracks += [

View file

@ -1,6 +1,8 @@
import os import os
from abc import ABC
from pathlib import Path from pathlib import Path
from shutil import copyfile from shutil import copyfile
from typing import Generic
from typing import Type from typing import Type
from typing import TypeVar from typing import TypeVar
@ -28,15 +30,11 @@ from ytdl_subscribe.validators.config.source_options.source_validator import (
from ytdl_subscribe.validators.config.source_options.source_validator import SourceValidator from ytdl_subscribe.validators.config.source_options.source_validator import SourceValidator
T = TypeVar("T", bound=SourceValidator) T = TypeVar("T", bound=SourceValidator)
U = TypeVar("U", bound=DownloadStrategyValidator) U = TypeVar("U", bound=Downloader)
V = TypeVar("V", bound=Downloader) V = TypeVar("V", bound=DownloadStrategyValidator)
class Subscription: class Subscription(Generic[T, V], ABC):
source_validator_type: Type[T]
download_strategy_type: Type[U]
downloader_type: Type[V]
def __init__( def __init__(
self, self,
name: str, name: str,
@ -55,13 +53,22 @@ class Subscription:
self.__config_options = config_options self.__config_options = config_options
self.__preset_options = preset_options self.__preset_options = preset_options
if not isinstance(preset_options.subscription_source, self.source_validator_type): @property
raise ValueError("Source options does not match the expected type") def source_options(self) -> T:
"""Returns the source options defined for this subscription"""
return self.__preset_options.subscription_source
if not isinstance( def get_downloader(self, downloader_type: Type[U]) -> U:
preset_options.subscription_source.download_strategy, self.download_strategy_type """Returns the downloader that will be used to download media for this subscription"""
): return downloader_type(
raise ValueError("Download strategy does not match the expected type") output_directory=self.working_directory,
ytdl_options=self.__preset_options.ytdl_options.dict,
)
@property
def download_strategy_options(self) -> V:
"""Returns the download strategy options defined for this subscription"""
return self.source_options.download_strategy
@property @property
def output_options(self) -> OutputOptionsValidator: def output_options(self) -> OutputOptionsValidator:
@ -73,16 +80,6 @@ class Subscription:
"""Returns the metadata options defined for this subscription""" """Returns the metadata options defined for this subscription"""
return self.__preset_options.metadata_options return self.__preset_options.metadata_options
@property
def source_options(self) -> T:
"""Returns the source options defined for this subscription"""
return self.__preset_options.subscription_source
@property
def download_strategy_options(self) -> U:
"""Returns the download strategy options defined for this subscription"""
return self.source_options.download_strategy
@property @property
def overrides(self) -> OverridesValidator: def overrides(self) -> OverridesValidator:
"""Returns the overrides defined for this subscription""" """Returns the overrides defined for this subscription"""
@ -93,14 +90,6 @@ class Subscription:
"""Returns the directory that the downloader saves files to""" """Returns the directory that the downloader saves files to"""
return str(Path(self.__config_options.working_directory.value) / Path(self.name)) return str(Path(self.__config_options.working_directory.value) / Path(self.name))
@property
def downloader(self) -> V:
"""Returns the downloader that will be used to download media for this subscription"""
return self.downloader_type(
output_directory=self.working_directory,
ytdl_options=self.__preset_options.ytdl_options.dict,
)
def _apply_formatter(self, entry: Entry, formatter: StringFormatterValidator) -> str: def _apply_formatter(self, entry: Entry, formatter: StringFormatterValidator) -> str:
""" """
Parameters Parameters

View file

@ -1,5 +1,3 @@
from abc import ABC
from ytdl_subscribe.downloaders.youtube_downloader import YoutubeDownloader from ytdl_subscribe.downloaders.youtube_downloader import YoutubeDownloader
from ytdl_subscribe.subscriptions.subscription import Subscription from ytdl_subscribe.subscriptions.subscription import Subscription
from ytdl_subscribe.validators.config.source_options.youtube_validators import ( from ytdl_subscribe.validators.config.source_options.youtube_validators import (
@ -10,28 +8,11 @@ from ytdl_subscribe.validators.config.source_options.youtube_validators import (
) )
class YoutubeSubscription(Subscription, ABC): class YoutubePlaylistSubscription(
source_validator_type = YoutubeSourceValidator Subscription[YoutubeSourceValidator, YoutubePlaylistDownloadValidator]
downloader_type = YoutubeDownloader ):
@property
def source_options(self) -> YoutubeSourceValidator:
return super().source_options
@property
def downloader(self) -> YoutubeDownloader:
return super().downloader
class YoutubePlaylistSubscription(YoutubeSubscription):
download_strategy_type = YoutubePlaylistDownloadValidator
@property
def download_strategy_options(self) -> YoutubePlaylistDownloadValidator:
return super().download_strategy_options
def extract_info(self): def extract_info(self):
entries = self.downloader.download_playlist( entries = self.get_downloader(YoutubeDownloader).download_playlist(
playlist_id=self.download_strategy_options.playlist_id.value playlist_id=self.download_strategy_options.playlist_id.value
) )