Merge pull request #368 from channelcat/blueprint-clarity

Restructured blueprint class for clarity
This commit is contained in:
Channel Cat 2017-01-29 18:47:27 -08:00 committed by GitHub
commit 38d1ed76d2

View File

@ -1,59 +1,12 @@
from collections import defaultdict from collections import defaultdict, namedtuple
class BlueprintSetup: FutureRoute = namedtuple('Route', ['handler', 'uri', 'methods', 'host'])
""" FutureListener = namedtuple('Listener', ['handler', 'uri', 'methods', 'host'])
Creates a blueprint state like object. FutureMiddleware = namedtuple('Route', ['middleware', 'args', 'kwargs'])
""" FutureException = namedtuple('Route', ['handler', 'args', 'kwargs'])
FutureStatic = namedtuple('Route',
def __init__(self, blueprint, app, options): ['uri', 'file_or_directory', 'args', 'kwargs'])
self.app = app
self.blueprint = blueprint
self.options = options
url_prefix = self.options.get('url_prefix')
if url_prefix is None:
url_prefix = self.blueprint.url_prefix
#: The prefix that should be used for all URLs defined on the
#: blueprint.
self.url_prefix = url_prefix
def add_route(self, handler, uri, methods, host=None):
"""
A helper method to register a handler to the application url routes.
"""
if self.url_prefix:
uri = self.url_prefix + uri
if host is None:
host = self.blueprint.host
self.app.route(uri=uri, methods=methods, host=host)(handler)
def add_exception(self, handler, *args, **kwargs):
"""
Registers exceptions to sanic.
"""
self.app.exception(*args, **kwargs)(handler)
def add_static(self, uri, file_or_directory, *args, **kwargs):
"""
Registers static files to sanic.
"""
if self.url_prefix:
uri = self.url_prefix + uri
self.app.static(uri, file_or_directory, *args, **kwargs)
def add_middleware(self, middleware, *args, **kwargs):
"""
Registers middleware to sanic.
"""
if args or kwargs:
self.app.middleware(*args, **kwargs)(middleware)
else:
self.app.middleware(middleware)
class Blueprint: class Blueprint:
@ -65,30 +18,49 @@ class Blueprint:
""" """
self.name = name self.name = name
self.url_prefix = url_prefix self.url_prefix = url_prefix
self.deferred_functions = []
self.listeners = defaultdict(list)
self.host = host self.host = host
def record(self, func): self.routes = []
""" self.exceptions = []
Registers a callback function that is invoked when the blueprint is self.listeners = defaultdict(list)
registered on the application. self.middlewares = []
""" self.statics = []
self.deferred_functions.append(func)
def make_setup_state(self, app, options):
"""
Returns a new BlueprintSetup object
"""
return BlueprintSetup(self, app, options)
def register(self, app, options): def register(self, app, options):
""" """
Registers the blueprint to the sanic app. Registers the blueprint to the sanic app.
""" """
state = self.make_setup_state(app, options)
for deferred in self.deferred_functions: url_prefix = options.get('url_prefix', self.url_prefix)
deferred(state)
# Routes
for future in self.routes:
# Prepend the blueprint URI prefix if available
uri = url_prefix + future.uri if url_prefix else future.uri
app.route(
uri=uri,
methods=future.methods,
host=future.host or self.host
)(future.handler)
# Middleware
for future in self.middlewares:
if future.args or future.kwargs:
app.middleware(*future.args,
**future.kwargs)(future.middleware)
else:
app.middleware(future.middleware)
# Exceptions
for future in self.exceptions:
app.exception(*future.args, **future.kwargs)(future.handler)
# Static Files
for future in self.statics:
# Prepend the blueprint URI prefix if available
uri = url_prefix + future.uri if url_prefix else future.uri
app.static(uri, future.file_or_directory,
*future.args, **future.kwargs)
def route(self, uri, methods=frozenset({'GET'}), host=None): def route(self, uri, methods=frozenset({'GET'}), host=None):
""" """
@ -97,7 +69,8 @@ class Blueprint:
:param methods: List of acceptable HTTP methods. :param methods: List of acceptable HTTP methods.
""" """
def decorator(handler): def decorator(handler):
self.record(lambda s: s.add_route(handler, uri, methods, host)) route = FutureRoute(handler, uri, methods, host)
self.routes.append(route)
return handler return handler
return decorator return decorator
@ -108,7 +81,8 @@ class Blueprint:
:param uri: Endpoint at which the route will be accessible. :param uri: Endpoint at which the route will be accessible.
:param methods: List of acceptable HTTP methods. :param methods: List of acceptable HTTP methods.
""" """
self.record(lambda s: s.add_route(handler, uri, methods, host)) route = FutureRoute(handler, uri, methods, host)
self.routes.append(route)
return handler return handler
def listener(self, event): def listener(self, event):
@ -125,10 +99,10 @@ class Blueprint:
""" """
Creates a blueprint middleware from a decorated function. Creates a blueprint middleware from a decorated function.
""" """
def register_middleware(middleware): def register_middleware(_middleware):
self.record( future_middleware = FutureMiddleware(_middleware, args, kwargs)
lambda s: s.add_middleware(middleware, *args, **kwargs)) self.middlewares.append(future_middleware)
return middleware return _middleware
# Detect which way this was called, @middleware or @middleware('AT') # Detect which way this was called, @middleware or @middleware('AT')
if len(args) == 1 and len(kwargs) == 0 and callable(args[0]): if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):
@ -143,7 +117,8 @@ class Blueprint:
Creates a blueprint exception from a decorated function. Creates a blueprint exception from a decorated function.
""" """
def decorator(handler): def decorator(handler):
self.record(lambda s: s.add_exception(handler, *args, **kwargs)) exception = FutureException(handler, args, kwargs)
self.exceptions.append(exception)
return handler return handler
return decorator return decorator
@ -153,5 +128,5 @@ class Blueprint:
:param uri: Endpoint at which the route will be accessible. :param uri: Endpoint at which the route will be accessible.
:param file_or_directory: Static asset. :param file_or_directory: Static asset.
""" """
self.record( static = FutureStatic(uri, file_or_directory, args, kwargs)
lambda s: s.add_static(uri, file_or_directory, *args, **kwargs)) self.statics.append(static)