Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: consistent exception naming #2420

Merged
merged 6 commits into from May 12, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions sanic/app.py
Expand Up @@ -58,7 +58,7 @@
from sanic.compat import OS_IS_WINDOWS, enable_windows_color_support
from sanic.config import SANIC_PREFIX, Config
from sanic.exceptions import (
InvalidUsage,
BadRequest,
SanicException,
ServerError,
URLBuildError,
Expand Down Expand Up @@ -275,7 +275,7 @@ def register_listener(
valid = ", ".join(
map(lambda x: x.lower(), ListenerEvent.__members__.keys())
)
raise InvalidUsage(f"Invalid event: {event}. Use one of: {valid}")
raise BadRequest(f"Invalid event: {event}. Use one of: {valid}")

if "." in _event:
self.signal(_event.value)(
Expand Down
4 changes: 2 additions & 2 deletions sanic/errorpages.py
Expand Up @@ -19,7 +19,7 @@
from functools import partial
from traceback import extract_tb

from sanic.exceptions import InvalidUsage, SanicException
from sanic.exceptions import BadRequest, SanicException
from sanic.helpers import STATUS_CODES
from sanic.request import Request
from sanic.response import HTTPResponse, html, json, text
Expand Down Expand Up @@ -506,7 +506,7 @@ def exception_response(
# $ curl localhost:8000 -d '{"foo": "bar"}'
# And provide them with JSONRenderer
renderer = JSONRenderer if request.json else base
except InvalidUsage:
except BadRequest:
renderer = base
else:
renderer = RENDERERS_BY_CONFIG.get(render_format, renderer)
Expand Down
28 changes: 20 additions & 8 deletions sanic/exceptions.py
Expand Up @@ -42,7 +42,7 @@ class NotFound(SanicException):
quiet = True


class InvalidUsage(SanicException):
class BadRequest(SanicException):
"""
**Status**: 400 Bad Request
"""
Expand All @@ -51,11 +51,14 @@ class InvalidUsage(SanicException):
quiet = True


class BadURL(InvalidUsage):
InvalidUsage = BadRequest


class BadURL(BadRequest):
...


class MethodNotSupported(SanicException):
class MethodNotAllowed(SanicException):
"""
**Status**: 405 Method Not Allowed
"""
Expand All @@ -68,6 +71,9 @@ def __init__(self, message, method, allowed_methods):
self.headers = {"Allow": ", ".join(allowed_methods)}


MethodNotSupported = MethodNotAllowed


class ServerError(SanicException):
"""
**Status**: 500 Internal Server Error
Expand Down Expand Up @@ -129,19 +135,19 @@ class PayloadTooLarge(SanicException):
quiet = True


class HeaderNotFound(InvalidUsage):
class HeaderNotFound(BadRequest):
"""
**Status**: 400 Bad Request
"""


class InvalidHeader(InvalidUsage):
class InvalidHeader(BadRequest):
"""
**Status**: 400 Bad Request
"""


class ContentRangeError(SanicException):
class RangeNotSatisfiable(SanicException):
"""
**Status**: 416 Range Not Satisfiable
"""
Expand All @@ -154,7 +160,10 @@ def __init__(self, message, content_range):
self.headers = {"Content-Range": f"bytes */{content_range.total}"}


class HeaderExpectationFailed(SanicException):
ContentRangeError = RangeNotSatisfiable


class ExpectationFailed(SanicException):
"""
**Status**: 417 Expectation Failed
"""
Expand All @@ -163,6 +172,9 @@ class HeaderExpectationFailed(SanicException):
quiet = True


HeaderExpectationFailed = ExpectationFailed


class Forbidden(SanicException):
"""
**Status**: 403 Forbidden
Expand All @@ -172,7 +184,7 @@ class Forbidden(SanicException):
quiet = True


class InvalidRangeType(ContentRangeError):
class InvalidRangeType(RangeNotSatisfiable):
"""
**Status**: 416 Range Not Satisfiable
"""
Expand Down
10 changes: 5 additions & 5 deletions sanic/handlers.py
Expand Up @@ -10,9 +10,9 @@
exception_response,
)
from sanic.exceptions import (
ContentRangeError,
HeaderNotFound,
InvalidRangeType,
RangeNotSatisfiable,
SanicException,
)
from sanic.helpers import Default, _default
Expand Down Expand Up @@ -296,18 +296,18 @@ def __init__(self, request, stats):
try:
self.start = int(start_b) if start_b else None
except ValueError:
raise ContentRangeError(
raise RangeNotSatisfiable(
"'%s' is invalid for Content Range" % (start_b,), self
)
try:
self.end = int(end_b) if end_b else None
except ValueError:
raise ContentRangeError(
raise RangeNotSatisfiable(
"'%s' is invalid for Content Range" % (end_b,), self
)
if self.end is None:
if self.start is None:
raise ContentRangeError(
raise RangeNotSatisfiable(
"Invalid for Content Range parameters", self
)
else:
Expand All @@ -319,7 +319,7 @@ def __init__(self, request, stats):
self.start = self.total - self.end
self.end = self.total - 1
if self.start >= self.end:
raise ContentRangeError(
raise RangeNotSatisfiable(
"Invalid for Content Range parameters", self
)
self.size = self.end - self.start + 1
Expand Down
24 changes: 12 additions & 12 deletions sanic/http.py
Expand Up @@ -12,8 +12,8 @@

from sanic.compat import Header
from sanic.exceptions import (
HeaderExpectationFailed,
InvalidUsage,
BadRequest,
ExpectationFailed,
PayloadTooLarge,
ServerError,
ServiceUnavailable,
Expand Down Expand Up @@ -53,14 +53,14 @@ class Http(metaclass=TouchUpMeta):
:raises ServerError:
:raises PayloadTooLarge:
:raises Exception:
:raises InvalidUsage:
:raises HeaderExpectationFailed:
:raises BadRequest:
:raises ExpectationFailed:
:raises RuntimeError:
:raises ServerError:
:raises ServerError:
:raises InvalidUsage:
:raises InvalidUsage:
:raises InvalidUsage:
:raises BadRequest:
:raises BadRequest:
:raises BadRequest:
:raises PayloadTooLarge:
:raises RuntimeError:
"""
Expand Down Expand Up @@ -248,7 +248,7 @@ async def http1_request_header(self): # no cov

headers.append(h)
except Exception:
raise InvalidUsage("Bad Request")
raise BadRequest("Bad Request")

headers_instance = Header(headers)
self.upgrade_websocket = (
Expand Down Expand Up @@ -281,7 +281,7 @@ async def http1_request_header(self): # no cov
if expect.lower() == "100-continue":
self.expecting_continue = True
else:
raise HeaderExpectationFailed(f"Unknown Expect: {expect}")
raise ExpectationFailed(f"Unknown Expect: {expect}")

if headers.getone("transfer-encoding", None) == "chunked":
self.request_body = "chunked"
Expand Down Expand Up @@ -510,22 +510,22 @@ async def read(self) -> Optional[bytes]: # no cov

if len(buf) > 64:
self.keep_alive = False
raise InvalidUsage("Bad chunked encoding")
raise BadRequest("Bad chunked encoding")

await self._receive_more()

try:
size = int(buf[2:pos].split(b";", 1)[0].decode(), 16)
except Exception:
self.keep_alive = False
raise InvalidUsage("Bad chunked encoding")
raise BadRequest("Bad chunked encoding")

if size <= 0:
self.request_body = None

if size < 0:
self.keep_alive = False
raise InvalidUsage("Bad chunked encoding")
raise BadRequest("Bad chunked encoding")

# Consume CRLF, chunk size 0 and the two CRLF that follow
pos += 4
Expand Down
4 changes: 2 additions & 2 deletions sanic/mixins/listeners.py
Expand Up @@ -3,7 +3,7 @@
from typing import Callable, List, Optional, Union, overload

from sanic.base.meta import SanicMeta
from sanic.exceptions import InvalidUsage
from sanic.exceptions import BadRequest
from sanic.models.futures import FutureListener
from sanic.models.handler_types import ListenerType, Sanic

Expand Down Expand Up @@ -86,7 +86,7 @@ def register_listener(

if callable(listener_or_event):
if event_or_none is None:
raise InvalidUsage(
raise BadRequest(
"Invalid event registration: Missing event name."
)
return register_listener(listener_or_event, event_or_none)
Expand Down
8 changes: 4 additions & 4 deletions sanic/mixins/routes.py
Expand Up @@ -18,10 +18,10 @@
from sanic.constants import DEFAULT_HTTP_CONTENT_TYPE, HTTP_METHODS
from sanic.errorpages import RESPONSE_MAPPING
from sanic.exceptions import (
ContentRangeError,
BadRequest,
FileNotFound,
HeaderNotFound,
InvalidUsage,
RangeNotSatisfiable,
)
from sanic.handlers import ContentRangeHandler
from sanic.log import deprecation, error_logger
Expand Down Expand Up @@ -778,7 +778,7 @@ async def _static_request_handler(
# Using this to determine if the URL is trying to break out of the path
# served. os.path.realpath seems to be very slow
if __file_uri__ and "../" in __file_uri__:
raise InvalidUsage("Invalid URL")
raise BadRequest("Invalid URL")
# Merge served directory and requested file if provided
# Strip all / that in the beginning of the URL to help prevent python
# from herping a derp and treating the uri as an absolute path
Expand Down Expand Up @@ -865,7 +865,7 @@ async def _static_request_handler(
file_path, headers=headers, _range=_range
)
return await file(file_path, headers=headers, _range=_range)
except ContentRangeError:
except RangeNotSatisfiable:
raise
except FileNotFoundError:
raise FileNotFound(
Expand Down
4 changes: 2 additions & 2 deletions sanic/models/asgi.py
Expand Up @@ -3,7 +3,7 @@

from typing import Any, Awaitable, Callable, MutableMapping, Optional, Union

from sanic.exceptions import InvalidUsage
from sanic.exceptions import BadRequest
from sanic.server.websockets.connection import WebSocketConnection


Expand Down Expand Up @@ -84,7 +84,7 @@ def get_websocket_connection(self) -> WebSocketConnection:
try:
return self._websocket_connection
except AttributeError:
raise InvalidUsage("Improper websocket connection.")
raise BadRequest("Improper websocket connection.")

def create_websocket_connection(
self, send: ASGISend, receive: ASGIReceive
Expand Down
4 changes: 2 additions & 2 deletions sanic/request.py
Expand Up @@ -34,7 +34,7 @@

from sanic.compat import CancelledErrors, Header
from sanic.constants import DEFAULT_HTTP_CONTENT_TYPE
from sanic.exceptions import BadURL, InvalidUsage, ServerError
from sanic.exceptions import BadRequest, BadURL, ServerError
from sanic.headers import (
AcceptContainer,
Options,
Expand Down Expand Up @@ -378,7 +378,7 @@ def load_json(self, loads=json_loads):
except Exception:
if not self.body:
return None
raise InvalidUsage("Failed when parsing body as json")
raise BadRequest("Failed when parsing body as json")

return self.parsed_json

Expand Down
4 changes: 2 additions & 2 deletions sanic/router.py
Expand Up @@ -14,7 +14,7 @@

from sanic.constants import HTTP_METHODS
from sanic.errorpages import check_error_format
from sanic.exceptions import MethodNotSupported, NotFound, SanicException
from sanic.exceptions import MethodNotAllowed, NotFound, SanicException
from sanic.models.handler_types import RouteHandler


Expand Down Expand Up @@ -43,7 +43,7 @@ def _get(
except RoutingNotFound as e:
raise NotFound("Requested URL {} not found".format(e.path))
except NoMethod as e:
raise MethodNotSupported(
raise MethodNotAllowed(
"Method {} not allowed for URL {}".format(method, path),
method=method,
allowed_methods=e.allowed_methods,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_asgi.py
Expand Up @@ -9,7 +9,7 @@
from sanic import Sanic
from sanic.application.state import Mode
from sanic.asgi import MockTransport
from sanic.exceptions import Forbidden, InvalidUsage, ServiceUnavailable
from sanic.exceptions import Forbidden, BadRequest, ServiceUnavailable
from sanic.request import Request
from sanic.response import json, text
from sanic.server.websockets.connection import WebSocketConnection
Expand Down Expand Up @@ -392,7 +392,7 @@ async def test_websocket_accept_with_multiple_subprotocols(


def test_improper_websocket_connection(transport, send, receive):
with pytest.raises(InvalidUsage):
with pytest.raises(BadRequest):
transport.get_websocket_connection()

transport.create_websocket_connection(send, receive)
Expand Down
6 changes: 3 additions & 3 deletions tests/test_blueprint_group.py
Expand Up @@ -5,7 +5,7 @@
from sanic.blueprints import Blueprint
from sanic.exceptions import (
Forbidden,
InvalidUsage,
BadRequest,
SanicException,
ServerError,
)
Expand Down Expand Up @@ -104,7 +104,7 @@ def blueprint_1_default_route(request):

@blueprint_1.route("/invalid")
def blueprint_1_error(request: Request):
raise InvalidUsage("Invalid")
raise BadRequest("Invalid")

@blueprint_2.route("/")
def blueprint_2_default_route(request):
Expand All @@ -120,7 +120,7 @@ def blueprint_2_error(request: Request):

blueprint_3 = Blueprint("blueprint_3", url_prefix="/bp3")

@blueprint_group_1.exception(InvalidUsage)
@blueprint_group_1.exception(BadRequest)
def handle_group_exception(request, exception):
return text("BP1_ERR_OK")

Expand Down