Removes the need for asycnio global settings

Also moves sanic.py -> app.py and removes the need for us to relative
import anymore.

This is a step towards allowing people to use things like
`sanic.get_event_loop()` instead of having to set global asyncio
settings.

Does not seem to work on 3.5.1 but works fine on every version after
that.
This commit is contained in:
Eli Uriegas 2017-01-31 14:34:26 -06:00
parent c91d264ff1
commit 7f85be43c6
5 changed files with 55 additions and 71 deletions

View File

@ -1,5 +1,6 @@
from .sanic import Sanic
from .blueprints import Blueprint
from sanic.app import Sanic
from sanic.blueprints import Blueprint
__version__ = '0.3.0'

View File

@ -1,23 +1,25 @@
import logging
from asyncio import get_event_loop
import multiprocessing
from collections import deque
from functools import partial
from inspect import isawaitable, stack, getmodulename
from traceback import format_exc
import warnings
from .config import Config
from .constants import HTTP_METHODS
from .exceptions import Handler
from .exceptions import ServerError
from .log import log
from .response import HTTPResponse
from .router import Router
from .server import serve, serve_multiple, HttpProtocol
from .static import register as static_register
from sanic.policy import get_event_loop
from sanic.config import Config
from sanic.constants import HTTP_METHODS
from sanic.exceptions import Handler
from sanic.exceptions import ServerError
from sanic.log import log
from sanic.response import HTTPResponse
from sanic.router import Router
from sanic.server import serve, serve_multiple, HttpProtocol
from sanic.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
@ -306,63 +308,43 @@ class Sanic:
:param protocol: Subclass of asyncio protocol class
:return: Nothing
"""
server_settings = self._helper(
server_settings = self._get_server_settings(
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)
log.info(
'Goin\' Fast @ {}://{}:{}'.format(
'https' if ssl else 'http', host, port))
try:
if workers == 1:
serve(**server_settings)
else:
serve_multiple(server_settings, workers, stop_event)
except Exception as e:
log.exception(
'Experienced exception while trying to serve')
log.info("Server Stopped")
def stop(self):
"""This kills the Sanic"""
for process in multiprocessing.active_children():
process.terminate()
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):
"""
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,
async_run=True)
# Serve
proto = "http"
if ssl is not None:
proto = "https"
log.info('Goin\' Fast @ {}://{}:{}'.format(proto, host, port))
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 _get_server_settings(
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):
"""
Helper function used by `run` and `create_server`.
"""
self.error_handler.debug = debug
self.debug = debug
self.loop = loop = get_event_loop()
if loop is not None:
if self.debug:
@ -396,8 +378,7 @@ class Sanic:
("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),
):
("after_server_stop", "after_stop", after_stop, True)):
listeners = []
for blueprint in self.blueprints.values():
listeners += blueprint.listeners[event_name]
@ -415,13 +396,4 @@ class Sanic:
log.setLevel(logging.DEBUG)
log.debug(self.config.LOGO)
if run_async:
server_settings['run_async'] = True
# Serve
proto = "http"
if ssl is not None:
proto = "https"
log.info('Goin\' Fast @ {}://{}:{}'.format(proto, host, port))
return server_settings

13
sanic/policy.py Normal file
View File

@ -0,0 +1,13 @@
import uvloop
_policy = uvloop.EventLoopPolicy()
def get_event_loop():
return _policy.get_event_loop()
def new_event_loop():
return _policy.new_event_loop()
def set_event_loop(loop):
_policy.set_event_loop(loop)

View File

@ -14,16 +14,11 @@ import warnings
from httptools import HttpRequestParser
from httptools.parser.errors import HttpParserError
from .exceptions import ServerError
try:
import uvloop as async_loop
except ImportError:
async_loop = asyncio
from .log import log
from .request import Request
from .exceptions import RequestTimeout, PayloadTooLarge, InvalidUsage
from sanic.policy import new_event_loop, set_event_loop
from sanic.log import log
from sanic.request import Request
from sanic.exceptions import (
RequestTimeout, PayloadTooLarge, InvalidUsage, ServerError)
current_time = None
@ -297,8 +292,8 @@ def serve(host, port, request_handler, error_handler, before_start=None,
:param protocol: Subclass of asyncio protocol class
:return: Nothing
"""
loop = async_loop.new_event_loop()
asyncio.set_event_loop(loop)
loop = new_event_loop()
set_event_loop(loop)
if debug:
loop.set_debug(debug)
@ -371,6 +366,8 @@ def serve(host, port, request_handler, error_handler, before_start=None,
trigger_events(after_stop, loop)
loop.stop()
loop.close()
@ -396,6 +393,8 @@ def serve_multiple(server_settings, workers, stop_event=None):
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
sock.bind((server_settings['host'], server_settings['port']))
set_inheritable(sock.fileno(), True)
host = server_settings['host']
port = server_settings['port']
server_settings['sock'] = sock
server_settings['host'] = None
server_settings['port'] = None
@ -420,5 +419,3 @@ def serve_multiple(server_settings, workers, stop_event=None):
for process in processes:
process.terminate()
sock.close()
asyncio.get_event_loop().stop()

View File

@ -29,10 +29,11 @@ def sanic_endpoint_test(app, method='get', uri='/', gather_request=True,
async def _collect_response(sanic, loop):
try:
response = await local_request(method, uri, *request_args,
**request_kwargs)
response = await local_request(
method, uri, *request_args, **request_kwargs)
results.append(response)
except Exception as e:
log.exception('Exception occured when collecting response')
exceptions.append(e)
app.stop()