Clean up exceptions

This commit is contained in:
Nathan Thomas 2023-12-21 20:48:02 -08:00
parent 4228525dc3
commit 3e297d9643
11 changed files with 36 additions and 86 deletions

View File

@ -7,7 +7,11 @@ import deezer
from Cryptodome.Cipher import AES
from ..config import Config
from ..exceptions import AuthenticationError, MissingCredentials, NonStreamable
from ..exceptions import (
AuthenticationError,
MissingCredentialsError,
NonStreamableError,
)
from .client import Client
from .downloadable import DeezerDownloadable
@ -41,7 +45,7 @@ class DeezerClient(Client):
self.session = await self.get_session()
arl = self.config.arl
if not arl:
raise MissingCredentials
raise MissingCredentialsError
success = self.client.login_via_arl(arl)
if not success:
raise AuthenticationError
@ -64,7 +68,7 @@ class DeezerClient(Client):
try:
item = await asyncio.to_thread(self.client.api.get_track, item_id)
except Exception as e:
raise NonStreamable(e)
raise NonStreamableError(e)
album_id = item["album"]["id"]
try:
@ -157,7 +161,7 @@ class DeezerClient(Client):
logger.debug("Fetching deezer url with token %s", token)
url = self.client.get_track_url(token, format_str)
except deezer.WrongLicense:
raise NonStreamable(
raise NonStreamableError(
"The requested quality is not available with your subscription. "
"Deezer HiFi is required for quality 2. Otherwise, the maximum "
"quality allowed is 1.",
@ -165,7 +169,7 @@ class DeezerClient(Client):
except deezer.WrongGeolocation:
if not is_retry:
return await self.get_downloadable(fallback_id, quality, is_retry=True)
raise NonStreamable(
raise NonStreamableError(
"The requested track is not available. This may be due to your country/location.",
)

View File

@ -21,7 +21,7 @@ from Cryptodome.Cipher import AES, Blowfish
from Cryptodome.Util import Counter
from .. import converter
from ..exceptions import NonStreamable
from ..exceptions import NonStreamableError
logger = logging.getLogger("streamrip")
@ -107,12 +107,12 @@ class DeezerDownloadable(Downloadable):
info = await resp.json()
try:
# Usually happens with deezloader downloads
raise NonStreamable(f"{info['error']} - {info['message']}")
raise NonStreamableError(f"{info['error']} - {info['message']}")
except KeyError:
raise NonStreamable(info)
raise NonStreamableError(info)
except json.JSONDecodeError:
raise NonStreamable("File not found.")
raise NonStreamableError("File not found.")
if self.is_encrypted.search(self.url) is None:
logger.debug(f"Deezer file at {self.url} not encrypted.")
@ -206,10 +206,10 @@ class TidalDownloadable(Downloadable):
# Turn CamelCase code into a readable sentence
if restrictions:
words = re.findall(r"([A-Z][a-z]+)", restrictions[0]["code"])
raise NonStreamable(
raise NonStreamableError(
words[0] + " " + " ".join(map(str.lower, words[1:])),
)
raise NonStreamable(
raise NonStreamableError(
f"Tidal download: dl_info = {url, codec, encryption_key}"
)
self.url = url

View File

@ -15,8 +15,8 @@ from ..exceptions import (
IneligibleError,
InvalidAppIdError,
InvalidAppSecretError,
MissingCredentials,
NonStreamable,
MissingCredentialsError,
NonStreamableError,
)
from .client import Client
from .downloadable import BasicDownloadable, Downloadable
@ -149,7 +149,7 @@ class QobuzClient(Client):
self.session = await self.get_session()
c = self.config.session.qobuz
if not c.email_or_userid or not c.password_or_token:
raise MissingCredentials
raise MissingCredentialsError
assert not self.logged_in, "Already logged in"
@ -226,7 +226,7 @@ class QobuzClient(Client):
status, resp = await self._api_request(epoint, params)
if status != 200:
raise NonStreamable(
raise NonStreamableError(
f'Error fetching metadata. Message: "{resp["message"]}"',
)
@ -313,10 +313,10 @@ class QobuzClient(Client):
if restrictions:
# Turn CamelCase code into a readable sentence
words = re.findall(r"([A-Z][a-z]+)", restrictions[0]["code"])
raise NonStreamable(
raise NonStreamableError(
words[0] + " " + " ".join(map(str.lower, words[1:])) + ".",
)
raise NonStreamable
raise NonStreamableError
return BasicDownloadable(
self.session,

View File

@ -4,7 +4,7 @@ import logging
import re
from ..config import Config
from ..exceptions import NonStreamable
from ..exceptions import NonStreamableError
from .client import Client
from .downloadable import SoundcloudDownloadable
@ -155,7 +155,7 @@ class SoundcloudClient(Client):
assert re.match(r"\d+", item_id) is not None
if download_info == self.NON_STREAMABLE:
raise NonStreamable(item_info)
raise NonStreamableError(item_info)
if download_info == self.ORIGINAL_DOWNLOAD:
resp_json, status = await self._api_request(f"tracks/{item_id}/download")
@ -183,7 +183,7 @@ class SoundcloudClient(Client):
offset: int = 0,
) -> list[dict]:
# TODO: implement pagination
assert media_type in ("track", "playlist")
assert media_type in ("track", "playlist"), f"Cannot search for {media_type}"
params = {
"q": query,
"facet": "genre",

View File

@ -115,7 +115,6 @@ class TidalClient(Client):
:type limit: int
:rtype: dict
"""
# TODD: paginate
params = {
"query": query,
"limit": limit,

View File

@ -1,5 +1,4 @@
"""Streamrip specific exceptions."""
from typing import List
from click import echo, style
@ -8,7 +7,7 @@ class AuthenticationError(Exception):
"""AuthenticationError."""
class MissingCredentials(Exception):
class MissingCredentialsError(Exception):
"""MissingCredentials."""
@ -27,11 +26,7 @@ class InvalidAppSecretError(Exception):
"""InvalidAppSecretError."""
class InvalidQuality(Exception):
"""InvalidQuality."""
class NonStreamable(Exception):
class NonStreamableError(Exception):
"""Item is not streamable.
A versatile error that can have many causes.
@ -71,50 +66,5 @@ class NonStreamable(Exception):
return " ".join(base_msg)
class InvalidContainerError(Exception):
"""InvalidContainerError."""
class InvalidSourceError(Exception):
"""InvalidSourceError."""
class ParsingError(Exception):
"""ParsingError."""
class TooLargeCoverArt(Exception):
"""TooLargeCoverArt."""
class BadEncoderOption(Exception):
"""BadEncoderOption."""
class ConversionError(Exception):
"""ConversionError."""
class NoResultsFound(Exception):
"""NoResultsFound."""
class ItemExists(Exception):
"""ItemExists."""
class PartialFailure(Exception):
"""Raise if part of a tracklist fails to download."""
def __init__(self, failed_items: List):
"""Create a PartialFailure exception.
:param failed_items:
:type failed_items: List
"""
self.failed_items = failed_items
super().__init__()
class FfmpegError(Exception):
"""Raise if ffmpeg returns nonzero exit code."""

View File

@ -7,7 +7,6 @@ from .. import progress
from ..client import Client
from ..config import Config
from ..db import Database
from ..exceptions import NonStreamable
from ..metadata import AlbumMetadata
from ..metadata.util import get_album_track_ids
from .artwork import download_artwork
@ -52,9 +51,8 @@ class PendingAlbum(Pending):
async def resolve(self) -> Album | None:
resp = await self.client.get_metadata(self.id, "album")
try:
meta = AlbumMetadata.from_album_resp(resp, self.client.source)
except NonStreamable:
meta = AlbumMetadata.from_album_resp(resp, self.client.source)
if meta is None:
logger.error(
f"Album {self.id} not available to stream on {self.client.source}",
)

View File

@ -15,7 +15,7 @@ from ..client import Client
from ..config import Config
from ..console import console
from ..db import Database
from ..exceptions import NonStreamable
from ..exceptions import NonStreamableError
from ..filepath_utils import clean_filename
from ..metadata import (
AlbumMetadata,
@ -47,7 +47,7 @@ class PendingPlaylistTrack(Pending):
return None
try:
resp = await self.client.get_metadata(self.id, "track")
except NonStreamable as e:
except NonStreamableError as e:
logger.error(f"Could not stream track {self.id}: {e}")
return None
@ -78,7 +78,7 @@ class PendingPlaylistTrack(Pending):
self._download_cover(album.covers, self.folder),
self.client.get_downloadable(self.id, quality),
)
except NonStreamable as e:
except NonStreamableError as e:
logger.error("Error fetching download info for track: %s", e)
self.db.set_failed(self.client.source, "track", self.id)
return None

View File

@ -7,7 +7,7 @@ from .. import converter
from ..client import Client, Downloadable
from ..config import Config
from ..db import Database
from ..exceptions import NonStreamable
from ..exceptions import NonStreamableError
from ..filepath_utils import clean_filename
from ..metadata import AlbumMetadata, Covers, TrackMetadata, tag_file
from ..progress import add_title, get_progress_callback, remove_title
@ -106,7 +106,7 @@ class PendingTrack(Pending):
source = self.client.source
try:
resp = await self.client.get_metadata(self.id, "track")
except NonStreamable as e:
except NonStreamableError as e:
logger.error(f"Track {self.id} not available for stream on {source}: {e}")
return None
@ -150,7 +150,7 @@ class PendingSingle(Pending):
try:
resp = await self.client.get_metadata(self.id, "track")
except NonStreamable as e:
except NonStreamableError as e:
logger.error(f"Error fetching track {self.id}: {e}")
return None
# Patch for soundcloud

View File

@ -70,7 +70,6 @@ class Covers:
@classmethod
def from_deezer(cls, resp):
c = cls()
# c.set_cover_url("original", "org".join(resp["cover_xl"].rsplit("600", 1)))
c.set_cover_url("original", resp["cover_xl"])
c.set_cover_url("large", resp["cover_big"])
c.set_cover_url("small", resp["cover_medium"])

View File

@ -10,7 +10,7 @@ from rich.prompt import Prompt
from ..client import Client, DeezerClient, QobuzClient, SoundcloudClient, TidalClient
from ..config import Config
from ..console import console
from ..exceptions import AuthenticationError, MissingCredentials
from ..exceptions import AuthenticationError, MissingCredentialsError
logger = logging.getLogger("streamrip")
@ -61,7 +61,7 @@ class QobuzPrompter(CredentialPrompter):
except AuthenticationError:
console.print("[yellow]Invalid credentials, try again.")
self._prompt_creds_and_set_session_config()
except MissingCredentials:
except MissingCredentialsError:
self._prompt_creds_and_set_session_config()
def _prompt_creds_and_set_session_config(self):