Recovery the issue 659

This commit is contained in:
lizheao 2017-04-27 17:50:04 +08:00
parent 472face796
commit 240f5b7c9f
3 changed files with 48 additions and 8 deletions

View File

@ -1,6 +1,8 @@
from collections import defaultdict, namedtuple
from types import MethodType
from sanic.constants import HTTP_METHODS
from sanic.exceptions import SanicTypeException
from sanic.views import CompositionView
FutureRoute = namedtuple('Route',
@ -93,10 +95,14 @@ class Blueprint:
:param uri: endpoint at which the route will be accessible.
:param methods: list of acceptable HTTP methods.
"""
def decorator(handler):
if isinstance(handler, MethodType):
raise SanicTypeException("You can`t add a instance method as a blueprint router hander")
route = FutureRoute(handler, uri, methods, host, strict_slashes)
self.routes.append(route)
return handler
return decorator
def add_route(self, handler, uri, methods=frozenset({'GET'}), host=None,
@ -120,6 +126,8 @@ class Blueprint:
# handle composition view differently
if isinstance(handler, CompositionView):
methods = handler.handlers.keys()
if isinstance(handler, MethodType):
raise SanicTypeException("You can`t add a instance method as a blueprint router hander")
self.route(uri=uri, methods=methods, host=host,
strict_slashes=strict_slashes)(handler)
@ -130,10 +138,12 @@ class Blueprint:
:param uri: endpoint at which the route will be accessible.
"""
def decorator(handler):
route = FutureRoute(handler, uri, [], host, strict_slashes)
self.websocket_routes.append(route)
return handler
return decorator
def add_websocket_route(self, handler, uri, host=None):
@ -152,13 +162,16 @@ class Blueprint:
:param event: Event to listen to.
"""
def decorator(listener):
self.listeners[event].append(listener)
return listener
return decorator
def middleware(self, *args, **kwargs):
"""Create a blueprint middleware from a decorated function."""
def register_middleware(_middleware):
future_middleware = FutureMiddleware(_middleware, args, kwargs)
self.middlewares.append(future_middleware)
@ -174,10 +187,12 @@ class Blueprint:
def exception(self, *args, **kwargs):
"""Create a blueprint exception from a decorated function."""
def decorator(handler):
exception = FutureException(handler, args, kwargs)
self.exceptions.append(exception)
return handler
return decorator
def static(self, uri, file_or_directory, *args, **kwargs):

View File

@ -97,7 +97,6 @@ INTERNAL_SERVER_ERROR_HTML = '''
class SanicException(Exception):
def __init__(self, message, status_code=None):
super().__init__(message)
@ -105,6 +104,10 @@ class SanicException(Exception):
self.status_code = status_code
class SanicTypeException(Exception):
pass
class NotFound(SanicException):
status_code = 404

View File

@ -1,10 +1,12 @@
import asyncio
import inspect
from sanic import Sanic
import pytest
from sanic import Sanic, response
from sanic.blueprints import Blueprint
from sanic.response import json, text
from sanic.exceptions import NotFound, ServerError, InvalidUsage
from sanic.exceptions import NotFound, ServerError, InvalidUsage, SanicTypeException
from sanic.response import text
# ------------------------------------------------------------ #
@ -134,7 +136,6 @@ def test_several_bp_with_host():
def handler2(request):
return text('Hello3')
app.blueprint(bp)
app.blueprint(bp2)
@ -201,7 +202,6 @@ def test_bp_exception_handler():
request, response = app.test_client.get('/1')
assert response.status == 400
request, response = app.test_client.get('/2')
assert response.status == 200
assert response.text == 'OK'
@ -349,3 +349,25 @@ def test_bp_shorthand():
'Sec-WebSocket-Version': '13'})
assert response.status == 101
assert ev.is_set()
def test_blueprint_handler_type_error():
class Manage(object):
def __init__(self):
self.blueprint = Blueprint(str(type(self).__name__))
self.blueprint.add_route(self.info, '/info')
async def info(self, request):
return response.json({'id': id(self)})
def register(self, app: Sanic):
app.blueprint(self.blueprint)
def myfunc():
app = Sanic()
manager = Manage()
manager.register(app)
with pytest.raises(SanicTypeException) as execinfo:
myfunc()
execinfo.match(r'.*?instance method.*?')