[exception] update exception hierarchy

- add InputError and ControlException base classes
- add ChallengeError, LoginRequired, AbortExtraction
- change code of NotFoundError from 8 to 4
  and NoExtractorError from 64 to 32
This commit is contained in:
Mike Fährmann
2025-07-09 17:57:19 +02:00
parent b77e18317b
commit 0fba5c98cb

View File

@@ -11,21 +11,26 @@
Class Hierarchy:
Exception
+-- GalleryDLException
+-- ExtractionError
| +-- AuthenticationError
| +-- AuthorizationError
| +-- NotFoundError
| +-- HttpError
+-- FormatError
| +-- FilenameFormatError
| +-- DirectoryFormatError
+-- FilterError
+-- InputFileError
+-- NoExtractorError
+-- StopExtraction
+-- TerminateExtraction
+-- RestartExtraction
└── GalleryDLException
├── ExtractionError
├── HttpError
│ └── ChallengeError
├── AuthorizationError
│ └── LoginRequired
│ ├── AuthenticationError
└── NotFoundError
├── InputError
│ ├── FormatError
│ │ ├── FilenameFormatError
│ │ └── DirectoryFormatError
│ ├── FilterError
│ ├── InputFileError
│ └── NoExtractorError
└── ControlException
├── StopExtraction
├── AbortExtraction
├── TerminateExtraction
└── RestartExtraction
"""
@@ -40,19 +45,22 @@ class GalleryDLException(Exception):
message = self.default
elif isinstance(message, Exception):
message = f"{message.__class__.__name__}: {message}"
if self.msgfmt and fmt:
message = self.msgfmt.format(message)
if fmt and self.msgfmt is not None:
message = self.msgfmt.replace("{}", message)
Exception.__init__(self, message)
###############################################################################
# Extractor Errors ############################################################
class ExtractionError(GalleryDLException):
"""Base class for exceptions during information extraction"""
code = 4
class HttpError(ExtractionError):
"""HTTP request during data extraction failed"""
default = "HTTP request failed"
code = 4
def __init__(self, message="", response=None):
self.response = response
@@ -66,16 +74,19 @@ class HttpError(ExtractionError):
ExtractionError.__init__(self, message)
class NotFoundError(ExtractionError):
"""Requested resource (gallery/image) could not be found"""
msgfmt = "Requested {} could not be found"
default = "resource (gallery/image)"
class ChallengeError(HttpError):
code = 8
def __init__(self, challenge, response):
message = (
f"{challenge} ({response.status_code} {response.reason}) "
f"for '{response.url}'")
HttpError.__init__(self, message, response)
class AuthenticationError(ExtractionError):
"""Invalid or missing login credentials"""
default = "Invalid or missing login credentials"
default = "Invalid login credentials"
code = 16
@@ -85,11 +96,28 @@ class AuthorizationError(ExtractionError):
code = 16
class FormatError(GalleryDLException):
"""Error while building output paths"""
class LoginRequired(AuthorizationError):
default = "Account credentials or cookies required"
class NotFoundError(ExtractionError):
"""Requested resource (gallery/image) could not be found"""
msgfmt = "Requested {} could not be found"
default = "resource (gallery/image)"
###############################################################################
# User Input ##################################################################
class InputError(GalleryDLException):
"""Error caused by user input and config options"""
code = 32
class FormatError(InputError):
"""Error while building output paths"""
class FilenameFormatError(FormatError):
"""Error while building output filenames"""
msgfmt = "Applying filename format string failed ({})"
@@ -100,40 +128,42 @@ class DirectoryFormatError(FormatError):
msgfmt = "Applying directory format string failed ({})"
class FilterError(GalleryDLException):
class FilterError(InputError):
"""Error while evaluating a filter expression"""
msgfmt = "Evaluating filter expression failed ({})"
code = 32
class InputFileError(GalleryDLException):
"""Error when parsing input file"""
code = 32
def __init__(self, message, *args):
GalleryDLException.__init__(
self, message % args if args else message)
class InputFileError(InputError):
"""Error when parsing an input file"""
class NoExtractorError(GalleryDLException):
class NoExtractorError(InputError):
"""No extractor can handle the given URL"""
code = 64
class StopExtraction(GalleryDLException):
###############################################################################
# Control Flow ################################################################
class ControlException(GalleryDLException):
code = 0
class StopExtraction(ControlException):
"""Stop data extraction"""
def __init__(self, message=None, *args):
GalleryDLException.__init__(self)
ControlException.__init__(self)
self.message = message % args if args else message
self.code = 1 if message else 0
class TerminateExtraction(GalleryDLException):
class AbortExtraction(ExtractionError, ControlException):
"""Abort data extraction due to an error"""
class TerminateExtraction(ControlException):
"""Terminate data extraction"""
code = 0
class RestartExtraction(GalleryDLException):
class RestartExtraction(ControlException):
"""Restart data extraction"""
code = 0