Browse Source

Typehint error.py

pull/7160/head
Rapptz 4 years ago
parent
commit
a8db8546db
  1. 90
      discord/errors.py

90
discord/errors.py

@ -22,6 +22,21 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
""" """
from __future__ import annotations
from typing import Dict, List, Optional, TYPE_CHECKING, Any, Tuple, Union
if TYPE_CHECKING:
from aiohttp import ClientResponse, ClientWebSocketResponse
try:
from requests import Response
ResponseType = Union[ClientResponse, Response]
except ModuleNotFoundError:
ResponseType = ClientResponse
from .interactions import Interaction
__all__ = ( __all__ = (
'DiscordException', 'DiscordException',
'ClientException', 'ClientException',
@ -39,41 +54,49 @@ __all__ = (
'InteractionResponded', 'InteractionResponded',
) )
class DiscordException(Exception): class DiscordException(Exception):
"""Base exception class for discord.py """Base exception class for discord.py
Ideally speaking, this could be caught to handle any exceptions raised from this library. Ideally speaking, this could be caught to handle any exceptions raised from this library.
""" """
pass pass
class ClientException(DiscordException): class ClientException(DiscordException):
"""Exception that's raised when an operation in the :class:`Client` fails. """Exception that's raised when an operation in the :class:`Client` fails.
These are usually for exceptions that happened due to user input. These are usually for exceptions that happened due to user input.
""" """
pass pass
class NoMoreItems(DiscordException): class NoMoreItems(DiscordException):
"""Exception that is raised when an async iteration operation has no more """Exception that is raised when an async iteration operation has no more items."""
items."""
pass pass
class GatewayNotFound(DiscordException): class GatewayNotFound(DiscordException):
"""An exception that is raised when the gateway for Discord could not be found""" """An exception that is raised when the gateway for Discord could not be found"""
def __init__(self): def __init__(self):
message = 'The gateway to connect to discord was not found.' message = 'The gateway to connect to discord was not found.'
super().__init__(message) super().__init__(message)
def flatten_error_dict(d, key=''):
items = [] def _flatten_error_dict(d: Dict[str, Any], key: str = '') -> Dict[str, str]:
items: List[Tuple[str, str]] = []
for k, v in d.items(): for k, v in d.items():
new_key = key + '.' + k if key else k new_key = key + '.' + k if key else k
if isinstance(v, dict): if isinstance(v, dict):
try: try:
_errors = v['_errors'] _errors: List[Dict[str, Any]] = v['_errors']
except KeyError: except KeyError:
items.extend(flatten_error_dict(v, new_key).items()) items.extend(_flatten_error_dict(v, new_key).items())
else: else:
items.append((new_key, ' '.join(x.get('message', '') for x in _errors))) items.append((new_key, ' '.join(x.get('message', '') for x in _errors)))
else: else:
@ -81,6 +104,7 @@ def flatten_error_dict(d, key=''):
return dict(items) return dict(items)
class HTTPException(DiscordException): class HTTPException(DiscordException):
"""Exception that's raised when an HTTP request operation fails. """Exception that's raised when an HTTP request operation fails.
@ -99,21 +123,23 @@ class HTTPException(DiscordException):
The Discord specific error code for the failure. The Discord specific error code for the failure.
""" """
def __init__(self, response, message): def __init__(self, response: ResponseType, message: Optional[Union[str, Dict[str, Any]]]):
self.response = response self.response: ResponseType = response
self.status = response.status self.status: int = response.status # type: ignore
self.code: int
self.text: str
if isinstance(message, dict): if isinstance(message, dict):
self.code = message.get('code', 0) self.code = message.get('code', 0)
base = message.get('message', '') base = message.get('message', '')
errors = message.get('errors') errors = message.get('errors')
if errors: if errors:
errors = flatten_error_dict(errors) errors = _flatten_error_dict(errors)
helpful = '\n'.join('In %s: %s' % t for t in errors.items()) helpful = '\n'.join('In %s: %s' % t for t in errors.items())
self.text = base + '\n' + helpful self.text = base + '\n' + helpful
else: else:
self.text = base self.text = base
else: else:
self.text = message self.text = message or ''
self.code = 0 self.code = 0
fmt = '{0.status} {0.reason} (error code: {1})' fmt = '{0.status} {0.reason} (error code: {1})'
@ -122,20 +148,25 @@ class HTTPException(DiscordException):
super().__init__(fmt.format(self.response, self.code, self.text)) super().__init__(fmt.format(self.response, self.code, self.text))
class Forbidden(HTTPException): class Forbidden(HTTPException):
"""Exception that's raised for when status code 403 occurs. """Exception that's raised for when status code 403 occurs.
Subclass of :exc:`HTTPException` Subclass of :exc:`HTTPException`
""" """
pass pass
class NotFound(HTTPException): class NotFound(HTTPException):
"""Exception that's raised for when status code 404 occurs. """Exception that's raised for when status code 404 occurs.
Subclass of :exc:`HTTPException` Subclass of :exc:`HTTPException`
""" """
pass pass
class DiscordServerError(HTTPException): class DiscordServerError(HTTPException):
"""Exception that's raised for when a 500 range status code occurs. """Exception that's raised for when a 500 range status code occurs.
@ -143,14 +174,18 @@ class DiscordServerError(HTTPException):
.. versionadded:: 1.5 .. versionadded:: 1.5
""" """
pass pass
class InvalidData(ClientException): class InvalidData(ClientException):
"""Exception that's raised when the library encounters unknown """Exception that's raised when the library encounters unknown
or invalid data from Discord. or invalid data from Discord.
""" """
pass pass
class InvalidArgument(ClientException): class InvalidArgument(ClientException):
"""Exception that's raised when an argument to a function """Exception that's raised when an argument to a function
is invalid some way (e.g. wrong value or wrong type). is invalid some way (e.g. wrong value or wrong type).
@ -159,15 +194,19 @@ class InvalidArgument(ClientException):
``TypeError`` except inherited from :exc:`ClientException` and thus ``TypeError`` except inherited from :exc:`ClientException` and thus
:exc:`DiscordException`. :exc:`DiscordException`.
""" """
pass pass
class LoginFailure(ClientException): class LoginFailure(ClientException):
"""Exception that's raised when the :meth:`Client.login` function """Exception that's raised when the :meth:`Client.login` function
fails to log you in from improper credentials or some other misc. fails to log you in from improper credentials or some other misc.
failure. failure.
""" """
pass pass
class ConnectionClosed(ClientException): class ConnectionClosed(ClientException):
"""Exception that's raised when the gateway connection is """Exception that's raised when the gateway connection is
closed for reasons that could not be handled internally. closed for reasons that could not be handled internally.
@ -181,15 +220,17 @@ class ConnectionClosed(ClientException):
shard_id: Optional[:class:`int`] shard_id: Optional[:class:`int`]
The shard ID that got closed if applicable. The shard ID that got closed if applicable.
""" """
def __init__(self, socket, *, shard_id, code=None):
def __init__(self, socket: ClientWebSocketResponse, *, shard_id: Optional[int], code: Optional[int] = None):
# This exception is just the same exception except # This exception is just the same exception except
# reconfigured to subclass ClientException for users # reconfigured to subclass ClientException for users
self.code = code or socket.close_code self.code: int = code or socket.close_code or -1
# aiohttp doesn't seem to consistently provide close reason # aiohttp doesn't seem to consistently provide close reason
self.reason = '' self.reason: str = ''
self.shard_id = shard_id self.shard_id: Optional[int] = shard_id
super().__init__(f'Shard ID {self.shard_id} WebSocket closed with {self.code}') super().__init__(f'Shard ID {self.shard_id} WebSocket closed with {self.code}')
class PrivilegedIntentsRequired(ClientException): class PrivilegedIntentsRequired(ClientException):
"""Exception that's raised when the gateway is requesting privileged intents """Exception that's raised when the gateway is requesting privileged intents
but they're not ticked in the developer page yet. but they're not ticked in the developer page yet.
@ -206,14 +247,17 @@ class PrivilegedIntentsRequired(ClientException):
The shard ID that got closed if applicable. The shard ID that got closed if applicable.
""" """
def __init__(self, shard_id): def __init__(self, shard_id: Optional[int]):
self.shard_id = shard_id self.shard_id: Optional[int] = shard_id
msg = 'Shard ID %s is requesting privileged intents that have not been explicitly enabled in the ' \ msg = (
'developer portal. It is recommended to go to https://discord.com/developers/applications/ ' \ 'Shard ID %s is requesting privileged intents that have not been explicitly enabled in the '
'and explicitly enable the privileged intents within your application\'s page. If this is not ' \ 'developer portal. It is recommended to go to https://discord.com/developers/applications/ '
'possible, then consider disabling the privileged intents instead.' 'and explicitly enable the privileged intents within your application\'s page. If this is not '
'possible, then consider disabling the privileged intents instead.'
)
super().__init__(msg % shard_id) super().__init__(msg % shard_id)
class InteractionResponded(ClientException): class InteractionResponded(ClientException):
"""Exception that's raised when sending another interaction response using """Exception that's raised when sending another interaction response using
:class:`InteractionResponse` when one has already been done before. :class:`InteractionResponse` when one has already been done before.
@ -228,6 +272,6 @@ class InteractionResponded(ClientException):
The interaction that's already been responded to. The interaction that's already been responded to.
""" """
def __init__(self, interaction): def __init__(self, interaction: Interaction):
self.interaction = interaction self.interaction: Interaction = interaction
super().__init__('This interaction has already been responded to before') super().__init__('This interaction has already been responded to before')

Loading…
Cancel
Save