Use app decorator instead of run arguments for before_start
Mirror listener of blueprints
This commit is contained in:
parent
75fca1b9c7
commit
b5e50ecb75
|
@ -7,15 +7,6 @@ keyword arguments:
|
|||
- `host` *(default `"127.0.0.1"`)*: Address to host the server on.
|
||||
- `port` *(default `8000`)*: Port to host the server on.
|
||||
- `debug` *(default `False`)*: Enables debug output (slows server).
|
||||
- `before_start` *(default `None`)*: Function or list of functions to be executed
|
||||
before the server starts accepting connections.
|
||||
- `after_start` *(default `None`)*: Function or list of functions to be executed
|
||||
after the server starts accepting connections.
|
||||
- `before_stop` *(default `None`)*: Function or list of functions to be
|
||||
executed when a stop signal is received before it is
|
||||
respected.
|
||||
- `after_stop` *(default `None`)*: Function or list of functions to be executed
|
||||
when all requests are complete.
|
||||
- `ssl` *(default `None`)*: `SSLContext` for SSL encryption of worker(s).
|
||||
- `sock` *(default `None`)*: Socket for the server to accept connections from.
|
||||
- `workers` *(default `1`)*: Number of worker processes to spawn.
|
||||
|
|
|
@ -8,6 +8,7 @@ app = Sanic(__name__)
|
|||
|
||||
sem = None
|
||||
|
||||
@app.listener('before_server_start')
|
||||
def init(sanic, loop):
|
||||
global sem
|
||||
CONCURRENCY_PER_WORKER = 4
|
||||
|
@ -33,4 +34,4 @@ async def test(request):
|
|||
return json(response)
|
||||
|
||||
|
||||
app.run(host="0.0.0.0", port=8000, workers=2, before_start=init)
|
||||
app.run(host="0.0.0.0", port=8000, workers=2)
|
||||
|
|
|
@ -26,6 +26,7 @@ async def get_pool():
|
|||
|
||||
app = Sanic(name=__name__)
|
||||
|
||||
@app.listener('before_server_start')
|
||||
async def prepare_db(app, loop):
|
||||
"""
|
||||
Let's create some table and add some data
|
||||
|
@ -61,5 +62,4 @@ async def handle(request):
|
|||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0',
|
||||
port=8000,
|
||||
debug=True,
|
||||
before_start=prepare_db)
|
||||
debug=True)
|
||||
|
|
|
@ -32,7 +32,7 @@ polls = sa.Table('sanic_polls', metadata,
|
|||
|
||||
app = Sanic(name=__name__)
|
||||
|
||||
|
||||
@app.listener('before_server_start')
|
||||
async def prepare_db(app, loop):
|
||||
""" Let's add some data
|
||||
|
||||
|
@ -58,9 +58,10 @@ async def handle(request):
|
|||
async with engine.acquire() as conn:
|
||||
result = []
|
||||
async for row in conn.execute(polls.select()):
|
||||
result.append({"question": row.question, "pub_date": row.pub_date})
|
||||
result.append({"question": row.question,
|
||||
"pub_date": row.pub_date})
|
||||
return json({"polls": result})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=8000, before_start=prepare_db)
|
||||
app.run(host='0.0.0.0', port=8000)
|
||||
|
|
|
@ -27,6 +27,7 @@ def jsonify(records):
|
|||
|
||||
app = Sanic(__name__)
|
||||
|
||||
@app.listener('before_server_start')
|
||||
async def create_db(app, loop):
|
||||
"""
|
||||
Create some table and add some data
|
||||
|
@ -55,4 +56,4 @@ async def handler(request):
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=8000, before_start=create_db)
|
||||
app.run(host='0.0.0.0', port=8000)
|
||||
|
|
|
@ -14,14 +14,6 @@ from peewee_async import Manager, PostgresqlDatabase
|
|||
|
||||
# we instantiate a custom loop so we can pass it to our db manager
|
||||
|
||||
def setup(app, loop):
|
||||
database = PostgresqlDatabase(database='test',
|
||||
host='127.0.0.1',
|
||||
user='postgres',
|
||||
password='mysecretpassword')
|
||||
|
||||
objects = Manager(database, loop=loop)
|
||||
|
||||
## from peewee_async docs:
|
||||
# Also there’s no need to connect and re-connect before executing async queries
|
||||
# with manager! It’s all automatic. But you can run Manager.connect() or
|
||||
|
@ -48,6 +40,15 @@ objects.database.allow_sync = False # this will raise AssertionError on ANY sync
|
|||
|
||||
app = Sanic('peewee_example')
|
||||
|
||||
@app.listener('before_server_start')
|
||||
def setup(app, loop):
|
||||
database = PostgresqlDatabase(database='test',
|
||||
host='127.0.0.1',
|
||||
user='postgres',
|
||||
password='mysecretpassword')
|
||||
|
||||
objects = Manager(database, loop=loop)
|
||||
|
||||
@app.route('/post/<key>/<value>')
|
||||
async def post(request, key, value):
|
||||
"""
|
||||
|
@ -75,4 +76,4 @@ async def get(request):
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host='0.0.0.0', port=8000, before_start=setup)
|
||||
app.run(host='0.0.0.0', port=8000)
|
||||
|
|
|
@ -64,12 +64,14 @@ def query_string(request):
|
|||
# Run Server
|
||||
# ----------------------------------------------- #
|
||||
|
||||
@app.listener('after_server_start')
|
||||
def after_start(app, loop):
|
||||
log.info("OH OH OH OH OHHHHHHHH")
|
||||
|
||||
|
||||
@app.listener('before_server_stop')
|
||||
def before_stop(app, loop):
|
||||
log.info("TRIED EVERYTHING")
|
||||
|
||||
|
||||
app.run(host="0.0.0.0", port=8000, debug=True, after_start=after_start, before_stop=before_stop)
|
||||
app.run(host="0.0.0.0", port=8000, debug=True)
|
||||
|
|
|
@ -65,6 +65,11 @@ class Blueprint:
|
|||
app.static(uri, future.file_or_directory,
|
||||
*future.args, **future.kwargs)
|
||||
|
||||
# Event listeners
|
||||
for event, listeners in self.listeners.items():
|
||||
for listener in listeners:
|
||||
app.listener(event)(listener)
|
||||
|
||||
def route(self, uri, methods=frozenset({'GET'}), host=None):
|
||||
"""
|
||||
Creates a blueprint route from a decorated function.
|
||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
|||
import re
|
||||
import warnings
|
||||
from asyncio import get_event_loop
|
||||
from collections import deque
|
||||
from collections import deque, defaultdict
|
||||
from functools import partial
|
||||
from inspect import isawaitable, stack, getmodulename
|
||||
from traceback import format_exc
|
||||
|
@ -10,8 +10,8 @@ from urllib.parse import urlencode, urlunparse
|
|||
|
||||
from .config import Config
|
||||
from .constants import HTTP_METHODS
|
||||
from .handlers import ErrorHandler
|
||||
from .exceptions import ServerError, URLBuildError
|
||||
from .handlers import ErrorHandler
|
||||
from .log import log
|
||||
from .response import HTTPResponse
|
||||
from .router import Router
|
||||
|
@ -20,6 +20,7 @@ from .static import register as static_register
|
|||
|
||||
|
||||
class Sanic:
|
||||
|
||||
def __init__(self, name=None, router=None,
|
||||
error_handler=None):
|
||||
# Only set up a default log handler if the
|
||||
|
@ -45,6 +46,7 @@ class Sanic:
|
|||
self.debug = None
|
||||
self.sock = None
|
||||
self.processes = None
|
||||
self.listeners = defaultdict(list)
|
||||
|
||||
# Register alternative method names
|
||||
self.go_fast = self.run
|
||||
|
@ -53,6 +55,18 @@ class Sanic:
|
|||
# Registration
|
||||
# -------------------------------------------------------------------- #
|
||||
|
||||
# Decorator
|
||||
def listener(self, event):
|
||||
"""
|
||||
Create a listener from a decorated function.
|
||||
|
||||
:param event: Event to listen to.
|
||||
"""
|
||||
def decorator(listener):
|
||||
self.listeners[event].append(listener)
|
||||
return listener
|
||||
return decorator
|
||||
|
||||
# Decorator
|
||||
def route(self, uri, methods=frozenset({'GET'}), host=None):
|
||||
"""
|
||||
|
@ -367,8 +381,7 @@ class Sanic:
|
|||
# Execution
|
||||
# -------------------------------------------------------------------- #
|
||||
|
||||
def run(self, host="127.0.0.1", port=8000, debug=False, before_start=None,
|
||||
after_start=None, before_stop=None, after_stop=None, ssl=None,
|
||||
def run(self, host="127.0.0.1", port=8000, debug=False, ssl=None,
|
||||
sock=None, workers=1, loop=None, protocol=HttpProtocol,
|
||||
backlog=100, stop_event=None, register_sys_signals=True):
|
||||
"""
|
||||
|
@ -378,14 +391,6 @@ class Sanic:
|
|||
:param host: Address to host on
|
||||
:param port: Port to host on
|
||||
:param debug: Enables debug output (slows server)
|
||||
:param before_start: Functions to be executed before the server starts
|
||||
accepting connections
|
||||
:param after_start: Functions to be executed after the server starts
|
||||
accepting connections
|
||||
:param before_stop: Functions to be executed when a stop signal is
|
||||
received before it is respected
|
||||
:param after_stop: Functions to be executed when all requests are
|
||||
complete
|
||||
:param ssl: SSLContext for SSL encryption of worker(s)
|
||||
:param sock: Socket for the server to accept connections from
|
||||
:param workers: Number of processes
|
||||
|
@ -398,11 +403,11 @@ class Sanic:
|
|||
:return: Nothing
|
||||
"""
|
||||
server_settings = self._helper(
|
||||
host=host, port=port, debug=debug, before_start=before_start,
|
||||
after_start=after_start, before_stop=before_stop,
|
||||
after_stop=after_stop, ssl=ssl, sock=sock, workers=workers,
|
||||
loop=loop, protocol=protocol, backlog=backlog,
|
||||
stop_event=stop_event, register_sys_signals=register_sys_signals)
|
||||
host=host, port=port, debug=debug, ssl=ssl, sock=sock,
|
||||
workers=workers, loop=loop, protocol=protocol, backlog=backlog,
|
||||
stop_event=stop_event, register_sys_signals=register_sys_signals
|
||||
)
|
||||
|
||||
try:
|
||||
if workers == 1:
|
||||
serve(**server_settings)
|
||||
|
@ -418,19 +423,16 @@ class Sanic:
|
|||
get_event_loop().stop()
|
||||
|
||||
async def create_server(self, host="127.0.0.1", port=8000, debug=False,
|
||||
before_start=None, after_start=None,
|
||||
before_stop=None, after_stop=None, ssl=None,
|
||||
sock=None, loop=None, protocol=HttpProtocol,
|
||||
backlog=100, stop_event=None):
|
||||
ssl=None, sock=None, loop=None,
|
||||
protocol=HttpProtocol, backlog=100,
|
||||
stop_event=None):
|
||||
"""
|
||||
Asynchronous version of `run`.
|
||||
"""
|
||||
server_settings = self._helper(
|
||||
host=host, port=port, debug=debug, before_start=before_start,
|
||||
after_start=after_start, before_stop=before_stop,
|
||||
after_stop=after_stop, ssl=ssl, sock=sock, loop=loop,
|
||||
protocol=protocol, backlog=backlog, stop_event=stop_event,
|
||||
run_async=True)
|
||||
server_settings = self._helper(host=host, port=port, debug=debug,
|
||||
ssl=ssl, sock=sock, loop=loop,
|
||||
protocol=protocol, backlog=backlog,
|
||||
stop_event=stop_event, run_async=True)
|
||||
|
||||
# Serve
|
||||
proto = "http"
|
||||
|
@ -440,11 +442,10 @@ class Sanic:
|
|||
|
||||
return await serve(**server_settings)
|
||||
|
||||
def _helper(self, host="127.0.0.1", port=8000, debug=False,
|
||||
before_start=None, after_start=None, before_stop=None,
|
||||
after_stop=None, ssl=None, sock=None, workers=1, loop=None,
|
||||
protocol=HttpProtocol, backlog=100, stop_event=None,
|
||||
register_sys_signals=True, run_async=False):
|
||||
def _helper(self, host="127.0.0.1", port=8000, debug=False, ssl=None,
|
||||
sock=None, workers=1, loop=None, protocol=HttpProtocol,
|
||||
backlog=100, stop_event=None, register_sys_signals=True,
|
||||
run_async=False):
|
||||
"""
|
||||
Helper function used by `run` and `create_server`.
|
||||
"""
|
||||
|
@ -481,19 +482,13 @@ class Sanic:
|
|||
# Register start/stop events
|
||||
# -------------------------------------------- #
|
||||
|
||||
for event_name, settings_name, args, reverse in (
|
||||
("before_server_start", "before_start", before_start, False),
|
||||
("after_server_start", "after_start", after_start, False),
|
||||
("before_server_stop", "before_stop", before_stop, True),
|
||||
("after_server_stop", "after_stop", after_stop, True),
|
||||
for event_name, settings_name, reverse in (
|
||||
("before_server_start", "before_start", False),
|
||||
("after_server_start", "after_start", False),
|
||||
("before_server_stop", "before_stop", True),
|
||||
("after_server_stop", "after_stop", True),
|
||||
):
|
||||
listeners = []
|
||||
for blueprint in self.blueprints.values():
|
||||
listeners += blueprint.listeners[event_name]
|
||||
if args:
|
||||
if callable(args):
|
||||
args = [args]
|
||||
listeners += args
|
||||
listeners = self.listeners[event_name].copy()
|
||||
if reverse:
|
||||
listeners.reverse()
|
||||
# Prepend sanic to the arguments when listeners are triggered
|
||||
|
|
|
@ -28,6 +28,7 @@ def sanic_endpoint_test(app, method='get', uri='/', gather_request=True,
|
|||
results[0] = request
|
||||
app.request_middleware.appendleft(_collect_request)
|
||||
|
||||
@app.listener('after_server_start') # TODO undo this
|
||||
async def _collect_response(sanic, loop):
|
||||
try:
|
||||
response = await local_request(method, uri, *request_args,
|
||||
|
@ -37,8 +38,8 @@ def sanic_endpoint_test(app, method='get', uri='/', gather_request=True,
|
|||
exceptions.append(e)
|
||||
app.stop()
|
||||
|
||||
app.run(host=HOST, debug=debug, port=PORT,
|
||||
after_start=_collect_response, **server_kwargs)
|
||||
app.run(host=HOST, debug=debug, port=PORT, **server_kwargs)
|
||||
app.listeners['after_server_start'].pop()
|
||||
|
||||
if exceptions:
|
||||
raise ValueError("Exception during request: {}".format(exceptions))
|
||||
|
|
|
@ -5,6 +5,7 @@ from sanic import Sanic
|
|||
def test_bad_request_response():
|
||||
app = Sanic('test_bad_request_response')
|
||||
lines = []
|
||||
@app.listener('after_server_start')
|
||||
async def _request(sanic, loop):
|
||||
connect = asyncio.open_connection('127.0.0.1', 42101)
|
||||
reader, writer = await connect
|
||||
|
@ -15,6 +16,6 @@ def test_bad_request_response():
|
|||
break
|
||||
lines.append(line)
|
||||
app.stop()
|
||||
app.run(host='127.0.0.1', port=42101, debug=False, after_start=_request)
|
||||
app.run(host='127.0.0.1', port=42101, debug=False)
|
||||
assert lines[0] == b'HTTP/1.1 400 Bad Request\r\n'
|
||||
assert lines[-1] == b'Error: Bad Request'
|
||||
|
|
|
@ -42,9 +42,10 @@ def test_single_listener(listener_name):
|
|||
random_name_app = Sanic(''.join(
|
||||
[choice(ascii_letters) for _ in range(choice(range(5, 10)))]))
|
||||
output = list()
|
||||
start_stop_app(
|
||||
random_name_app,
|
||||
**{listener_name: create_listener(listener_name, output)})
|
||||
# Register listener
|
||||
random_name_app.listener(listener_name)(
|
||||
create_listener(listener_name, output))
|
||||
start_stop_app(random_name_app)
|
||||
assert random_name_app.name + listener_name == output.pop()
|
||||
|
||||
|
||||
|
@ -52,9 +53,9 @@ def test_all_listeners():
|
|||
random_name_app = Sanic(''.join(
|
||||
[choice(ascii_letters) for _ in range(choice(range(5, 10)))]))
|
||||
output = list()
|
||||
start_stop_app(
|
||||
random_name_app,
|
||||
**{listener_name: create_listener(listener_name, output)
|
||||
for listener_name in AVAILABLE_LISTENERS})
|
||||
for listener_name in AVAILABLE_LISTENERS:
|
||||
listener = create_listener(listener_name, output)
|
||||
random_name_app.listener(listener_name)(listener)
|
||||
start_stop_app(random_name_app)
|
||||
for listener_name in AVAILABLE_LISTENERS:
|
||||
assert random_name_app.name + listener_name == output.pop()
|
||||
|
|
|
@ -27,10 +27,11 @@ def test_register_system_signals():
|
|||
async def hello_route(request):
|
||||
return HTTPResponse()
|
||||
|
||||
app.run(HOST, PORT,
|
||||
before_start=set_loop,
|
||||
after_start=stop,
|
||||
after_stop=after)
|
||||
app.listener('after_server_start')(stop)
|
||||
app.listener('before_server_start')(set_loop)
|
||||
app.listener('after_server_stop')(after)
|
||||
|
||||
app.run(HOST, PORT)
|
||||
assert calledq.get() == True
|
||||
|
||||
|
||||
|
@ -42,9 +43,9 @@ def test_dont_register_system_signals():
|
|||
async def hello_route(request):
|
||||
return HTTPResponse()
|
||||
|
||||
app.run(HOST, PORT,
|
||||
before_start=set_loop,
|
||||
after_start=stop,
|
||||
after_stop=after,
|
||||
register_sys_signals=False)
|
||||
app.listener('after_server_start')(stop)
|
||||
app.listener('before_server_start')(set_loop)
|
||||
app.listener('after_server_stop')(after)
|
||||
|
||||
app.run(HOST, PORT, register_sys_signals=False)
|
||||
assert calledq.get() == False
|
||||
|
|
Loading…
Reference in New Issue
Block a user