Source code for gd.errors

from gd.typing import TYPE_CHECKING, Any, Optional, TypeVar

__all__ = (
    "GDException",
    "HTTPException",
    "HTTPError",
    "HTTPStatusError",
    "ClientException",
    "MissingAccess",
    "SongRestricted",
    "CommentBanned",
    "LoginFailure",
    "LoginRequired",
    "NothingFound",
    "DataException",
    "DeError",
    "SerError",
    "XMLError",
    "EditorError",
)

T = TypeVar("T")
U = TypeVar("U")

if TYPE_CHECKING:
    from gd.model_backend import Field  # type: ignore  # noqa


[docs]class GDException(Exception): """Base exception class for gd.py. This could be caught to handle any exceptions thrown from this library. """ pass
[docs]class HTTPException(GDException): """Base exception class for errors that are thrown when operation in :class:`~gd.HTTPClient` fails. """ pass
[docs]class HTTPError(HTTPException): """Exception that is raised when exception in :class:`~gd.HTTPClient` occurs. """ def __init__(self, origin: BaseException) -> None: self._origin = origin super().__init__(f"Failed to process HTTP request. {type(origin).__name__}: {origin}") @property def origin(self) -> BaseException: """:class:`BaseException`: The original exception that was raised.""" return self._origin
[docs]class HTTPStatusError(HTTPException): """Exception that is raised when error status code is returned. Error codes are considered to be ``4XX`` (client errors) and ``5XX`` (server errors). """ def __init__(self, status: int, reason: Optional[Any]) -> None: self._status = status self._reason = reason super().__init__(f"{status} {reason}") @property def status(self): return self._status @property def reason(self): return self._reason
[docs]class ClientException(GDException): """Base exception class for errors that are thrown when operation in :class:`~gd.Client` fails. """ pass
[docs]class MissingAccess(ClientException): """Exception that is raised when server responses with an error.""" pass
[docs]class SongRestricted(ClientException): """Exception that is raised when server returns an error when looking for a song.""" def __init__(self, id: int) -> None: self._id = id super().__init__(f"Song with id {id!r} is not allowed for use.") @property def id(self) -> int: """ID of the song that is restricted.""" return self._id
[docs]class LoginFailure(ClientException): """Exception that is raised when server returns an error when trying to log in. """ def __init__(self, name: str, password: str) -> None: self._name = name self._password = password super().__init__(f"Failed to login with credentials: {name!r} -> {password!r}.") @property def name(self) -> str: """Username that was wrong or password did not match.""" return self._name @property def password(self) -> str: """Password that login was failed with.""" return self._password
class CommentBanned(ClientException): """Exception that is raised when the client is temporarily or permanently banned from commenting. """ PERMANENT = "Permanently banned from posting comments. Reason: {reason}" TEMPORARY = "Banned for {timeout}s from posting comments. Reason: {reason}" DEFAULT_REASON = "Not provided." def __init__(self, timeout: Optional[int] = None, reason: Optional[str] = None) -> None: self._timeout = timeout self._reason = reason super().__init__(self.message) @property def message(self) -> str: timeout = self.timeout reason = self.reason if reason is None: reason = self.DEFAULT_REASON if timeout is None: return self.PERMANENT.format(reason=reason) return self.TEMPORARY.format(timeout=timeout, reason=reason) @property def timeout(self) -> Optional[int]: return self._timeout @property def reason(self) -> Optional[str]: return self._reason class LoginRequired(ClientException): """Exception that is raised when the client is not logged in when required.""" pass
[docs]class NothingFound(ClientException): """Exception that is raised when server returns nothing. It is raised by :class:`~gd.HTTPClient`, and automatically handled by :class:`~gd.Client`. So, if one is working on lower level, i.e. :class:`~gd.HTTPClient` or :class:`~gd.Session`, they should handle it as well. """ def __init__(self, instance_name: str) -> None: self._instance_name = instance_name super().__init__(f"No {instance_name!r} instances were found.") @property def instance_name(self) -> str: """Name of the class instances of which were not found.""" return self._instance_name
[docs]class DataException(GDException): """Base exception class for errors that are raised when parsing RobTop's data fails. """ pass
[docs]class SerError(DataException): """Exception that is raised when serializing data fails.""" def __init__( self, data: T, index: U, field: Optional["Field"], origin: Optional[BaseException], ) -> None: self._data = data self._index = index self._field = field self._origin = origin lines = [f"Failed to serialize {data!r} at index {index!r}."] if field: lines.append(f"[Type] {type(data)!r} -> {field.type!r}") lines.append(f"[Function] {field.ser!r}") if origin: lines.append(f"[Origin] {type(origin).__name__}: {origin}") super().__init__("\n".join(lines)) @property def data(self) -> T: return self._data @property def index(self) -> U: return self._index # type: ignore @property def field(self) -> Optional["Field"]: return self._field @property def origin(self) -> Optional[BaseException]: return self._origin
[docs]class DeError(DataException): """Exception that is raised if deserializing data fails.""" def __init__( self, data: str, index: U, field: Optional["Field"], origin: Optional[BaseException], ) -> None: self._data = data self._index = index self._field = field self._origin = origin lines = [f"Failed to deserialize {data!r} at index {index!r}."] if field: lines.append(f"[Type] {type(data)!r} -> {field.type!r}") lines.append(f"[Function] {field.de!r}") if origin: lines.append(f"[Origin] {type(origin).__name__}: {origin}") super().__init__("\n".join(lines)) @property def data(self) -> str: return self._data @property def index(self) -> U: return self._index # type: ignore @property def field(self) -> Optional["Field"]: return self._field @property def origin(self) -> Optional[BaseException]: return self._origin
[docs]class XMLError(DataException): """Exception that is raised if conversion in :class:`~gd.XMLParser` fails.""" pass
[docs]class EditorError(DataException): """Exception that is raised when converting string in :class:`~gd.api.Editor` failed.""" pass