remove loop as argument and update examples

This commit is contained in:
Raphael Deem 2017-01-21 18:26:32 -08:00
parent 2774414f9e
commit d52f5f0b09
9 changed files with 109 additions and 124 deletions

View File

@ -1,12 +1,8 @@
from sanic import Sanic from sanic import Sanic
from sanic.response import json from sanic.response import json
import uvloop
import aiohttp import aiohttp
#Create an event loop manually so that we can use it for both sanic & aiohttp
loop = uvloop.new_event_loop()
app = Sanic(__name__) app = Sanic(__name__)
async def fetch(session, url): async def fetch(session, url):
@ -24,10 +20,9 @@ async def test(request):
""" """
url = "https://api.github.com/repos/channelcat/sanic" url = "https://api.github.com/repos/channelcat/sanic"
async with aiohttp.ClientSession(loop=loop) as session: async with aiohttp.ClientSession() as session:
response = await fetch(session, url) response = await fetch(session, url)
return json(response) return json(response)
app.run(host="0.0.0.0", port=8000, loop=loop) app.run(host="0.0.0.0", port=8000, workers=2)

View File

@ -10,8 +10,6 @@ import aiopg
from sanic import Sanic from sanic import Sanic
from sanic.response import json from sanic.response import json
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
database_name = os.environ['DATABASE_NAME'] database_name = os.environ['DATABASE_NAME']
database_host = os.environ['DATABASE_HOST'] database_host = os.environ['DATABASE_HOST']
database_user = os.environ['DATABASE_USER'] database_user = os.environ['DATABASE_USER']
@ -21,45 +19,47 @@ connection = 'postgres://{0}:{1}@{2}/{3}'.format(database_user,
database_password, database_password,
database_host, database_host,
database_name) database_name)
loop = asyncio.get_event_loop()
async def get_pool(): async def get_pool():
return await aiopg.create_pool(connection) return await aiopg.create_pool(connection)
app = Sanic(name=__name__) app = Sanic(name=__name__)
pool = loop.run_until_complete(get_pool())
async def prepare_db():
""" Let's create some table and add some data
async def prepare_db(app, loop):
""" """
async with pool.acquire() as conn: Let's create some table and add some data
async with conn.cursor() as cur: """
await cur.execute('DROP TABLE IF EXISTS sanic_polls') async with aiopg.create_pool(connection) as pool:
await cur.execute("""CREATE TABLE sanic_polls ( async with pool.acquire() as conn:
id serial primary key, async with conn.cursor() as cur:
question varchar(50), await cur.execute('DROP TABLE IF EXISTS sanic_polls')
pub_date timestamp await cur.execute("""CREATE TABLE sanic_polls (
);""") id serial primary key,
for i in range(0, 100): question varchar(50),
await cur.execute("""INSERT INTO sanic_polls pub_date timestamp
(id, question, pub_date) VALUES ({}, {}, now()) );""")
""".format(i, i)) for i in range(0, 100):
await cur.execute("""INSERT INTO sanic_polls
(id, question, pub_date) VALUES ({}, {}, now())
""".format(i, i))
@app.route("/") @app.route("/")
async def handle(request): async def handle(request):
async with pool.acquire() as conn: result = []
async with conn.cursor() as cur: async def test_select():
result = [] async with aiopg.create_pool(connection) as pool:
await cur.execute("SELECT question, pub_date FROM sanic_polls") async with pool.acquire() as conn:
async for row in cur: async with conn.cursor() as cur:
result.append({"question": row[0], "pub_date": row[1]}) await cur.execute("SELECT question, pub_date FROM sanic_polls")
return json({"polls": result}) async for row in cur:
result.append({"question": row[0], "pub_date": row[1]})
res = await test_select()
return json({'polls': result})
if __name__ == '__main__': if __name__ == '__main__':
loop.run_until_complete(prepare_db()) app.run(host='0.0.0.0',
app.run(host='0.0.0.0', port=8000, loop=loop) port=8000,
debug=True,
before_start=prepare_db)

View File

@ -12,8 +12,6 @@ import sqlalchemy as sa
from sanic import Sanic from sanic import Sanic
from sanic.response import json from sanic.response import json
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
database_name = os.environ['DATABASE_NAME'] database_name = os.environ['DATABASE_NAME']
database_host = os.environ['DATABASE_HOST'] database_host = os.environ['DATABASE_HOST']
database_user = os.environ['DATABASE_USER'] database_user = os.environ['DATABASE_USER']
@ -23,8 +21,6 @@ connection = 'postgres://{0}:{1}@{2}/{3}'.format(database_user,
database_password, database_password,
database_host, database_host,
database_name) database_name)
loop = asyncio.get_event_loop()
metadata = sa.MetaData() metadata = sa.MetaData()
@ -34,40 +30,37 @@ polls = sa.Table('sanic_polls', metadata,
sa.Column("pub_date", sa.DateTime)) sa.Column("pub_date", sa.DateTime))
async def get_engine():
return await create_engine(connection)
app = Sanic(name=__name__) app = Sanic(name=__name__)
engine = loop.run_until_complete(get_engine())
async def prepare_db(): async def prepare_db(app, loop):
""" Let's add some data """ Let's add some data
""" """
async with engine.acquire() as conn: async with create_engine(connection) as engine:
await conn.execute('DROP TABLE IF EXISTS sanic_polls') async with engine.acquire() as conn:
await conn.execute("""CREATE TABLE sanic_polls ( await conn.execute('DROP TABLE IF EXISTS sanic_polls')
id serial primary key, await conn.execute("""CREATE TABLE sanic_polls (
question varchar(50), id serial primary key,
pub_date timestamp question varchar(50),
);""") pub_date timestamp
for i in range(0, 100): );""")
await conn.execute( for i in range(0, 100):
polls.insert().values(question=i, await conn.execute(
pub_date=datetime.datetime.now()) polls.insert().values(question=i,
) pub_date=datetime.datetime.now())
)
@app.route("/") @app.route("/")
async def handle(request): async def handle(request):
async with engine.acquire() as conn: async with create_engine(connection) as engine:
result = [] async with engine.acquire() as conn:
async for row in conn.execute(polls.select()): result = []
result.append({"question": row.question, "pub_date": row.pub_date}) async for row in conn.execute(polls.select()):
return json({"polls": result}) result.append({"question": row.question, "pub_date": row.pub_date})
return json({"polls": result})
if __name__ == '__main__': if __name__ == '__main__':
loop.run_until_complete(prepare_db()) app.run(host='0.0.0.0', port=8000, before_start=prepare_db)
app.run(host='0.0.0.0', port=8000, loop=loop)

View File

@ -10,8 +10,6 @@ from asyncpg import create_pool
from sanic import Sanic from sanic import Sanic
from sanic.response import json from sanic.response import json
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
DB_CONFIG = { DB_CONFIG = {
'host': '<host>', 'host': '<host>',
'user': '<username>', 'user': '<username>',
@ -21,45 +19,40 @@ DB_CONFIG = {
} }
def jsonify(records): def jsonify(records):
""" Parse asyncpg record response into JSON format """
Parse asyncpg record response into JSON format
""" """
return [{key: value for key, value in return [{key: value for key, value in
zip(r.keys(), r.values())} for r in records] zip(r.keys(), r.values())} for r in records]
loop = asyncio.get_event_loop()
async def make_pool():
return await create_pool(**DB_CONFIG)
app = Sanic(__name__) app = Sanic(__name__)
pool = loop.run_until_complete(make_pool())
async def create_db():
""" Create some table and add some data
async def create_db(app, loop):
""" """
async with pool.acquire() as connection: Create some table and add some data
async with connection.transaction(): """
await connection.execute('DROP TABLE IF EXISTS sanic_post') async with create_pool(**DB_CONFIG) as pool:
await connection.execute("""CREATE TABLE sanic_post ( async with pool.acquire() as connection:
id serial primary key, async with connection.transaction():
content varchar(50), await connection.execute('DROP TABLE IF EXISTS sanic_post')
post_date timestamp await connection.execute("""CREATE TABLE sanic_post (
);""") id serial primary key,
for i in range(0, 100): content varchar(50),
await connection.execute(f"""INSERT INTO sanic_post post_date timestamp
(id, content, post_date) VALUES ({i}, {i}, now())""") );""")
for i in range(0, 100):
await connection.execute(f"""INSERT INTO sanic_post
(id, content, post_date) VALUES ({i}, {i}, now())""")
@app.route("/") @app.route("/")
async def handler(request): async def handler(request):
async with pool.acquire() as connection: async with create_pool(**DB_CONFIG) as pool:
async with connection.transaction(): async with pool.acquire() as connection:
results = await connection.fetch('SELECT * FROM sanic_post') async with connection.transaction():
return json({'posts': jsonify(results)}) results = await connection.fetch('SELECT * FROM sanic_post')
return json({'posts': jsonify(results)})
if __name__ == '__main__': if __name__ == '__main__':
loop.run_until_complete(create_db()) app.run(host='0.0.0.0', port=8000, before_start=create_db)
app.run(host='0.0.0.0', port=8000, loop=loop)

View File

@ -9,19 +9,18 @@ from sanic import Sanic
from sanic.response import json from sanic.response import json
## peewee_async related imports ## peewee_async related imports
import uvloop
import peewee import peewee
from peewee_async import Manager, PostgresqlDatabase from peewee_async import Manager, PostgresqlDatabase
# we instantiate a custom loop so we can pass it to our db manager # we instantiate a custom loop so we can pass it to our db manager
loop = uvloop.new_event_loop()
database = PostgresqlDatabase(database='test', def setup(app, loop):
host='127.0.0.1', database = PostgresqlDatabase(database='test',
user='postgres', host='127.0.0.1',
password='mysecretpassword') user='postgres',
password='mysecretpassword')
objects = Manager(database, loop=loop) objects = Manager(database, loop=loop)
## from peewee_async docs: ## from peewee_async docs:
# Also theres no need to connect and re-connect before executing async queries # Also theres no need to connect and re-connect before executing async queries
@ -76,5 +75,4 @@ async def get(request):
if __name__ == "__main__": if __name__ == "__main__":
app.run(host='0.0.0.0', port=8000, loop=loop) app.run(host='0.0.0.0', port=8000, before_start=setup)

View File

@ -42,7 +42,6 @@ class Sanic:
self.response_middleware = deque() self.response_middleware = deque()
self.blueprints = {} self.blueprints = {}
self._blueprint_order = [] self._blueprint_order = []
self.loop = None
self.debug = None self.debug = None
self.sock = None self.sock = None
self.processes = None self.processes = None
@ -275,8 +274,8 @@ class Sanic:
def run(self, host="127.0.0.1", port=8000, debug=False, before_start=None, 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, after_start=None, before_stop=None, after_stop=None, ssl=None,
sock=None, workers=1, loop=None, protocol=HttpProtocol, sock=None, workers=1, protocol=HttpProtocol, backlog=100,
backlog=100, stop_event=None, register_sys_signals=True): stop_event=None, register_sys_signals=True):
""" """
Runs the HTTP Server and listens until keyboard interrupt or term Runs the HTTP Server and listens until keyboard interrupt or term
signal. On termination, drains connections before closing. signal. On termination, drains connections before closing.
@ -296,7 +295,6 @@ class Sanic:
:param sock: Socket for the server to accept connections from :param sock: Socket for the server to accept connections from
:param workers: Number of processes :param workers: Number of processes
received before it is respected received before it is respected
:param loop: asyncio compatible event loop
:param protocol: Subclass of asyncio protocol class :param protocol: Subclass of asyncio protocol class
:return: Nothing :return: Nothing
""" """
@ -319,7 +317,6 @@ class Sanic:
'error_handler': self.error_handler, 'error_handler': self.error_handler,
'request_timeout': self.config.REQUEST_TIMEOUT, 'request_timeout': self.config.REQUEST_TIMEOUT,
'request_max_size': self.config.REQUEST_MAX_SIZE, 'request_max_size': self.config.REQUEST_MAX_SIZE,
'loop': loop,
'register_sys_signals': register_sys_signals, 'register_sys_signals': register_sys_signals,
'backlog': backlog 'backlog': backlog
} }

View File

@ -289,7 +289,7 @@ def serve(host, port, request_handler, error_handler, before_start=None,
:param protocol: Subclass of asyncio protocol class :param protocol: Subclass of asyncio protocol class
:return: Nothing :return: Nothing
""" """
loop = loop or async_loop.new_event_loop() loop = async_loop.new_event_loop()
asyncio.set_event_loop(loop) asyncio.set_event_loop(loop)
if debug: if debug:

View File

@ -16,7 +16,7 @@ async def local_request(method, uri, cookies=None, *args, **kwargs):
def sanic_endpoint_test(app, method='get', uri='/', gather_request=True, def sanic_endpoint_test(app, method='get', uri='/', gather_request=True,
loop=None, debug=False, server_kwargs={}, debug=False, server_kwargs={},
*request_args, **request_kwargs): *request_args, **request_kwargs):
results = [] results = []
exceptions = [] exceptions = []
@ -36,7 +36,7 @@ def sanic_endpoint_test(app, method='get', uri='/', gather_request=True,
app.stop() app.stop()
app.run(host=HOST, debug=debug, port=PORT, app.run(host=HOST, debug=debug, port=PORT,
after_start=_collect_response, loop=loop, **server_kwargs) after_start=_collect_response, **server_kwargs)
if exceptions: if exceptions:
raise ValueError("Exception during request: {}".format(exceptions)) raise ValueError("Exception during request: {}".format(exceptions))

View File

@ -4,12 +4,20 @@ from sanic.utils import HOST, PORT
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest import pytest
import asyncio import asyncio
from queue import Queue
async def stop(app): async def stop(app, loop):
await asyncio.sleep(0.2) await asyncio.sleep(0.1)
app.stop() app.stop()
calledq = Queue()
def set_loop(app, loop):
loop.add_signal_handler = MagicMock()
def after(app, loop):
calledq.put(loop.add_signal_handler.called)
def test_register_system_signals(): def test_register_system_signals():
"""Test if sanic register system signals""" """Test if sanic register system signals"""
@ -19,11 +27,11 @@ def test_register_system_signals():
async def hello_route(request): async def hello_route(request):
return HTTPResponse() return HTTPResponse()
loop = asyncio.new_event_loop() app.run(HOST, PORT,
loop.add_signal_handler = MagicMock() before_start=set_loop,
asyncio.ensure_future(stop(app), loop=loop) after_start=stop,
app.run(HOST, PORT, loop=loop) after_stop=after)
assert loop.add_signal_handler.called == True assert calledq.get() == True
def test_dont_register_system_signals(): def test_dont_register_system_signals():
@ -34,8 +42,9 @@ def test_dont_register_system_signals():
async def hello_route(request): async def hello_route(request):
return HTTPResponse() return HTTPResponse()
loop = asyncio.new_event_loop() app.run(HOST, PORT,
loop.add_signal_handler = MagicMock() before_start=set_loop,
asyncio.ensure_future(stop(app), loop=loop) after_start=stop,
app.run(HOST, PORT, loop=loop, register_sys_signals=False) after_stop=after,
assert loop.add_signal_handler.called == False register_sys_signals=False)
assert calledq.get() == False