diff --git a/sanic/sanic.py b/sanic/sanic.py index a3342653..361581e9 100644 --- a/sanic/sanic.py +++ b/sanic/sanic.py @@ -306,6 +306,84 @@ class Sanic: :param protocol: Subclass of asyncio protocol class :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) + 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""" + 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) + + server_settings['run_async'] = 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): + """ + Runs the HTTP Server and listens until keyboard interrupt or term + signal. On termination, drains connections before closing. + + :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 + received before it is respected + :param protocol: Subclass of asyncio protocol class + :return: Nothing + """ + self.error_handler.debug = debug self.debug = debug self.loop = loop @@ -365,83 +443,4 @@ class Sanic: if ssl is not None: proto = "https" log.info('Goin\' Fast @ {}://{}:{}'.format(proto, 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""" - 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`. - """ - if loop is not None: - if self.debug: - warnings.simplefilter('default') - warnings.warn("Passing a loop will be deprecated in version" - " 0.4.0 https://github.com/channelcat/sanic/" - "pull/335 has more information.", - DeprecationWarning) - - loop = get_event_loop() - server_settings = { - 'protocol': protocol, - 'host': host, - 'port': port, - 'sock': sock, - 'ssl': ssl, - 'debug': debug, - 'request_handler': self.handle_request, - 'error_handler': self.error_handler, - 'request_timeout': self.config.REQUEST_TIMEOUT, - 'request_max_size': self.config.REQUEST_MAX_SIZE, - 'loop': loop, - 'backlog': backlog - } - - # -------------------------------------------- # - # 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)): - listeners = [] - for blueprint in self.blueprints.values(): - listeners += blueprint.listeners[event_name] - if args: - if callable(args): - args = [args] - listeners += args - if reverse: - listeners.reverse() - # Prepend sanic to the arguments when listeners are triggered - listeners = [partial(listener, self) for listener in listeners] - server_settings[settings_name] = listeners - - server_settings['run_async'] = True - - # Serve - proto = "http" - if ssl is not None: - proto = "https" - log.info('Goin\' Fast @ {}://{}:{}'.format(proto, host, port)) - - return await serve(**server_settings) + return server_settings diff --git a/sanic/server.py b/sanic/server.py index be9bc31c..48c3827e 100644 --- a/sanic/server.py +++ b/sanic/server.py @@ -297,8 +297,8 @@ def serve(host, port, request_handler, error_handler, before_start=None, :param protocol: Subclass of asyncio protocol class :return: Nothing """ - loop = asyncio.get_event_loop() - asyncio.set_event_loop_policy(async_loop.EventLoopPolicy()) + loop = async_loop.new_event_loop() + asyncio.set_event_loop(loop) if debug: loop.set_debug(debug) diff --git a/tests/test_loop_policy.py b/tests/test_loop_policy.py deleted file mode 100644 index f764548c..00000000 --- a/tests/test_loop_policy.py +++ /dev/null @@ -1,27 +0,0 @@ -from sanic import Sanic -import asyncio -from signal import signal, SIGINT -import uvloop - - -def test_loop_policy(): - app = Sanic('test_loop_policy') - - server = app.create_server(host="0.0.0.0", port=8000) - - loop = asyncio.get_event_loop() - task = asyncio.ensure_future(server) - signal(SIGINT, lambda s, f: loop.close()) - - # serve() sets the event loop policy to uvloop but - # doesn't get called until we run the server task - assert isinstance(asyncio.get_event_loop_policy(), - asyncio.unix_events._UnixDefaultEventLoopPolicy) - - try: - loop.run_until_complete(task) - except: - loop.stop() - - assert isinstance(asyncio.get_event_loop_policy(), - uvloop.EventLoopPolicy)