Replace stream decorator to stream parameter

This commit is contained in:
38elements 2017-05-09 22:31:15 +09:00
parent 4d4f38fb35
commit 6a14e49479
8 changed files with 257 additions and 57 deletions

View File

@ -33,7 +33,7 @@ async def index(request):
## Request Streaming ## Request Streaming
Sanic allows you to get request data by stream, as below. When the request ends, `request.stream.get()` returns `None`. Sanic allows you to get request data by stream, as below. When the request ends, `request.stream.get()` returns `None`. Only post, put and patch decorator have stream argument.
```python ```python
from sanic import Sanic from sanic import Sanic
@ -60,7 +60,7 @@ class SimpleView(HTTPMethodView):
return text(result) return text(result)
@app.stream('/stream') @app.post('/stream', stream=True)
async def handler(request): async def handler(request):
async def streaming(response): async def streaming(response):
while True: while True:
@ -72,7 +72,7 @@ async def handler(request):
return stream(streaming) return stream(streaming)
@bp.stream('/bp_stream') @bp.put('/bp_stream', stream=True)
async def bp_handler(request): async def bp_handler(request):
result = '' result = ''
while True: while True:

View File

@ -6,5 +6,5 @@ data = ""
for i in range(1, 250000): for i in range(1, 250000):
data += str(i) data += str(i)
r = requests.post('http://127.0.0.1:8000/method_view', data=data) r = requests.post('http://127.0.0.1:8000/stream', data=data)
print(r.text) print(r.text)

View File

@ -22,7 +22,7 @@ class SimpleView(HTTPMethodView):
return text(result) return text(result)
@app.stream('/stream') @app.post('/stream', stream=True)
async def handler(request): async def handler(request):
async def streaming(response): async def streaming(response):
while True: while True:
@ -34,7 +34,7 @@ async def handler(request):
return stream(streaming) return stream(streaming)
@bp.stream('/bp_stream') @bp.put('/bp_stream', stream=True)
async def bp_handler(request): async def bp_handler(request):
result = '' result = ''
while True: while True:

View File

@ -144,13 +144,13 @@ class Sanic:
return self.route(uri, methods=frozenset({"GET"}), host=host, return self.route(uri, methods=frozenset({"GET"}), host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes)
def post(self, uri, host=None, strict_slashes=False): def post(self, uri, host=None, strict_slashes=False, stream=False):
return self.route(uri, methods=frozenset({"POST"}), host=host, return self.route(uri, methods=frozenset({"POST"}), host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes, stream=stream)
def put(self, uri, host=None, strict_slashes=False): def put(self, uri, host=None, strict_slashes=False, stream=False):
return self.route(uri, methods=frozenset({"PUT"}), host=host, return self.route(uri, methods=frozenset({"PUT"}), host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes, stream=stream)
def head(self, uri, host=None, strict_slashes=False): def head(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=frozenset({"HEAD"}), host=host, return self.route(uri, methods=frozenset({"HEAD"}), host=host,
@ -160,21 +160,14 @@ class Sanic:
return self.route(uri, methods=frozenset({"OPTIONS"}), host=host, return self.route(uri, methods=frozenset({"OPTIONS"}), host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes)
def patch(self, uri, host=None, strict_slashes=False): def patch(self, uri, host=None, strict_slashes=False, stream=False):
return self.route(uri, methods=frozenset({"PATCH"}), host=host, return self.route(uri, methods=frozenset({"PATCH"}), host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes, stream=stream)
def delete(self, uri, host=None, strict_slashes=False): def delete(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=frozenset({"DELETE"}), host=host, return self.route(uri, methods=frozenset({"DELETE"}), host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes)
def stream(
self, uri, methods=frozenset({"POST"}), host=None,
strict_slashes=False):
return self.route(uri, methods=methods, host=host,
strict_slashes=strict_slashes,
stream=True)
def add_route(self, handler, uri, methods=frozenset({'GET'}), host=None, def add_route(self, handler, uri, methods=frozenset({'GET'}), host=None,
strict_slashes=False): strict_slashes=False):
"""A helper method to register class instance or """A helper method to register class instance or

View File

@ -196,13 +196,13 @@ class Blueprint:
return self.route(uri, methods=["GET"], host=host, return self.route(uri, methods=["GET"], host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes)
def post(self, uri, host=None, strict_slashes=False): def post(self, uri, host=None, strict_slashes=False, stream=False):
return self.route(uri, methods=["POST"], host=host, return self.route(uri, methods=["POST"], host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes, stream=stream)
def put(self, uri, host=None, strict_slashes=False): def put(self, uri, host=None, strict_slashes=False, stream=False):
return self.route(uri, methods=["PUT"], host=host, return self.route(uri, methods=["PUT"], host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes, stream=stream)
def head(self, uri, host=None, strict_slashes=False): def head(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=["HEAD"], host=host, return self.route(uri, methods=["HEAD"], host=host,
@ -212,14 +212,10 @@ class Blueprint:
return self.route(uri, methods=["OPTIONS"], host=host, return self.route(uri, methods=["OPTIONS"], host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes)
def patch(self, uri, host=None, strict_slashes=False): def patch(self, uri, host=None, strict_slashes=False, stream=False):
return self.route(uri, methods=["PATCH"], host=host, return self.route(uri, methods=["PATCH"], host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes, stream=stream)
def delete(self, uri, host=None, strict_slashes=False): def delete(self, uri, host=None, strict_slashes=False):
return self.route(uri, methods=["DELETE"], host=host, return self.route(uri, methods=["DELETE"], host=host,
strict_slashes=strict_slashes) strict_slashes=strict_slashes)
def stream(self, uri, methods=["POST"], host=None, strict_slashes=False):
return self.route(uri, methods=methods, host=host,
strict_slashes=strict_slashes, stream=True)

View File

@ -17,7 +17,6 @@ def test_bp():
@bp.route('/') @bp.route('/')
def handler(request): def handler(request):
assert request.stream is None
return text('Hello') return text('Hello')
app.blueprint(bp) app.blueprint(bp)
@ -270,38 +269,48 @@ def test_bp_shorthand():
@blueprint.get('/get') @blueprint.get('/get')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
@blueprint.put('/put') @blueprint.put('/put')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
@blueprint.post('/post') @blueprint.post('/post')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
@blueprint.head('/head') @blueprint.head('/head')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
@blueprint.options('/options') @blueprint.options('/options')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
@blueprint.patch('/patch') @blueprint.patch('/patch')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
@blueprint.delete('/delete') @blueprint.delete('/delete')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
@blueprint.websocket('/ws') @blueprint.websocket('/ws')
async def handler(request, ws): async def handler(request, ws):
assert request.stream is None
ev.set() ev.set()
app.blueprint(blueprint) app.blueprint(blueprint)
assert app.is_request_stream is False
request, response = app.test_client.get('/get') request, response = app.test_client.get('/get')
assert response.text == 'OK' assert response.text == 'OK'

View File

@ -45,12 +45,37 @@ def test_request_stream_method_view():
def test_request_stream_app(): def test_request_stream_app():
'''for self.is_request_stream = True''' '''for self.is_request_stream = True and decorators'''
app = Sanic('test_request_stream_app') app = Sanic('test_request_stream_app')
@app.stream('/stream') @app.get('/get')
async def handler(request): async def get(request):
assert request.stream is None
return text('GET')
@app.head('/head')
async def head(request):
assert request.stream is None
return text('HEAD')
@app.delete('/delete')
async def delete(request):
assert request.stream is None
return text('DELETE')
@app.options('/options')
async def options(request):
assert request.stream is None
return text('OPTIONS')
@app.post('/_post/<id>')
async def _post(request, id):
assert request.stream is None
return text('_POST')
@app.post('/post/<id>', stream=True)
async def post(request, id):
assert isinstance(request.stream, asyncio.Queue) assert isinstance(request.stream, asyncio.Queue)
async def streaming(response): async def streaming(response):
@ -61,18 +86,79 @@ def test_request_stream_app():
response.write(body.decode('utf-8')) response.write(body.decode('utf-8'))
return stream(streaming) return stream(streaming)
@app.get('/get') @app.put('/_put')
async def get(request): async def _put(request):
assert request.stream is None assert request.stream is None
return text('OK') return text('_PUT')
@app.put('/put', stream=True)
async def put(request):
assert isinstance(request.stream, asyncio.Queue)
async def streaming(response):
while True:
body = await request.stream.get()
if body is None:
break
response.write(body.decode('utf-8'))
return stream(streaming)
@app.patch('/_patch')
async def _patch(request):
assert request.stream is None
return text('_PATCH')
@app.patch('/patch', stream=True)
async def patch(request):
assert isinstance(request.stream, asyncio.Queue)
async def streaming(response):
while True:
body = await request.stream.get()
if body is None:
break
response.write(body.decode('utf-8'))
return stream(streaming)
assert app.is_request_stream is True assert app.is_request_stream is True
request, response = app.test_client.get('/get') request, response = app.test_client.get('/get')
assert response.status == 200 assert response.status == 200
assert response.text == 'OK' assert response.text == 'GET'
request, response = app.test_client.post('/stream', data=data) request, response = app.test_client.head('/head')
assert response.status == 200
assert response.text == ''
request, response = app.test_client.delete('/delete')
assert response.status == 200
assert response.text == 'DELETE'
request, response = app.test_client.options('/options')
assert response.status == 200
assert response.text == 'OPTIONS'
request, response = app.test_client.post('/_post/1', data=data)
assert response.status == 200
assert response.text == '_POST'
request, response = app.test_client.post('/post/1', data=data)
assert response.status == 200
assert response.text == data
request, response = app.test_client.put('/_put', data=data)
assert response.status == 200
assert response.text == '_PUT'
request, response = app.test_client.put('/put', data=data)
assert response.status == 200
assert response.text == data
request, response = app.test_client.patch('/_patch', data=data)
assert response.status == 200
assert response.text == '_PATCH'
request, response = app.test_client.patch('/patch', data=data)
assert response.status == 200 assert response.status == 200
assert response.text == data assert response.text == data
@ -83,31 +169,118 @@ def test_request_stream_blueprint():
app = Sanic('test_request_stream_blueprint') app = Sanic('test_request_stream_blueprint')
bp = Blueprint('test_blueprint_request_stream_blueprint') bp = Blueprint('test_blueprint_request_stream_blueprint')
@bp.stream('/bp_stream') @app.get('/get')
async def bp_stream(request): async def get(request):
assert isinstance(request.stream, asyncio.Queue)
result = ''
while True:
body = await request.stream.get()
if body is None:
break
result += body.decode('utf-8')
return text(result)
@bp.get('/bp_get')
async def bp_get(request):
assert request.stream is None assert request.stream is None
return text('OK') return text('GET')
@bp.head('/head')
async def head(request):
assert request.stream is None
return text('HEAD')
@bp.delete('/delete')
async def delete(request):
assert request.stream is None
return text('DELETE')
@bp.options('/options')
async def options(request):
assert request.stream is None
return text('OPTIONS')
@bp.post('/_post/<id>')
async def _post(request, id):
assert request.stream is None
return text('_POST')
@bp.post('/post/<id>', stream=True)
async def post(request, id):
assert isinstance(request.stream, asyncio.Queue)
async def streaming(response):
while True:
body = await request.stream.get()
if body is None:
break
response.write(body.decode('utf-8'))
return stream(streaming)
@bp.put('/_put')
async def _put(request):
assert request.stream is None
return text('_PUT')
@bp.put('/put', stream=True)
async def put(request):
assert isinstance(request.stream, asyncio.Queue)
async def streaming(response):
while True:
body = await request.stream.get()
if body is None:
break
response.write(body.decode('utf-8'))
return stream(streaming)
@bp.patch('/_patch')
async def _patch(request):
assert request.stream is None
return text('_PATCH')
@bp.patch('/patch', stream=True)
async def patch(request):
assert isinstance(request.stream, asyncio.Queue)
async def streaming(response):
while True:
body = await request.stream.get()
if body is None:
break
response.write(body.decode('utf-8'))
return stream(streaming)
app.blueprint(bp) app.blueprint(bp)
assert app.is_request_stream is True assert app.is_request_stream is True
request, response = app.test_client.get('/bp_get') request, response = app.test_client.get('/get')
assert response.status == 200 assert response.status == 200
assert response.text == 'OK' assert response.text == 'GET'
request, response = app.test_client.post('/bp_stream', data=data) request, response = app.test_client.head('/head')
assert response.status == 200
assert response.text == ''
request, response = app.test_client.delete('/delete')
assert response.status == 200
assert response.text == 'DELETE'
request, response = app.test_client.options('/options')
assert response.status == 200
assert response.text == 'OPTIONS'
request, response = app.test_client.post('/_post/1', data=data)
assert response.status == 200
assert response.text == '_POST'
request, response = app.test_client.post('/post/1', data=data)
assert response.status == 200
assert response.text == data
request, response = app.test_client.put('/_put', data=data)
assert response.status == 200
assert response.text == '_PUT'
request, response = app.test_client.put('/put', data=data)
assert response.status == 200
assert response.text == data
request, response = app.test_client.patch('/_patch', data=data)
assert response.status == 200
assert response.text == '_PATCH'
request, response = app.test_client.patch('/patch', data=data)
assert response.status == 200 assert response.status == 200
assert response.text == data assert response.text == data
@ -170,7 +343,7 @@ def test_request_stream():
result += body.decode('utf-8') result += body.decode('utf-8')
return text(result) return text(result)
@app.stream('/stream') @app.post('/stream', stream=True)
async def handler(request): async def handler(request):
assert isinstance(request.stream, asyncio.Queue) assert isinstance(request.stream, asyncio.Queue)
@ -187,7 +360,7 @@ def test_request_stream():
assert request.stream is None assert request.stream is None
return text('OK') return text('OK')
@bp.stream('/bp_stream') @bp.post('/bp_stream', stream=True)
async def bp_stream(request): async def bp_stream(request):
assert isinstance(request.stream, asyncio.Queue) assert isinstance(request.stream, asyncio.Queue)
result = '' result = ''

View File

@ -33,6 +33,7 @@ def test_route_strict_slash():
@app.post('/post/', strict_slashes=True) @app.post('/post/', strict_slashes=True)
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
assert app.is_request_stream is False assert app.is_request_stream is False
@ -80,21 +81,43 @@ def test_shorthand_routes_put():
@app.put('/put') @app.put('/put')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
assert app.is_request_stream is False
request, response = app.test_client.put('/put') request, response = app.test_client.put('/put')
assert response.text == 'OK' assert response.text == 'OK'
request, response = app.test_client.get('/put') request, response = app.test_client.get('/put')
assert response.status == 405 assert response.status == 405
def test_shorthand_routes_delete():
app = Sanic('test_shorhand_routes_delete')
@app.delete('/delete')
def handler(request):
assert request.stream is None
return text('OK')
assert app.is_request_stream is False
request, response = app.test_client.delete('/delete')
assert response.text == 'OK'
request, response = app.test_client.get('/delete')
assert response.status == 405
def test_shorthand_routes_patch(): def test_shorthand_routes_patch():
app = Sanic('test_shorhand_routes_patch') app = Sanic('test_shorhand_routes_patch')
@app.patch('/patch') @app.patch('/patch')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
assert app.is_request_stream is False
request, response = app.test_client.patch('/patch') request, response = app.test_client.patch('/patch')
assert response.text == 'OK' assert response.text == 'OK'
@ -106,8 +129,11 @@ def test_shorthand_routes_head():
@app.head('/head') @app.head('/head')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
assert app.is_request_stream is False
request, response = app.test_client.head('/head') request, response = app.test_client.head('/head')
assert response.status == 200 assert response.status == 200
@ -119,8 +145,11 @@ def test_shorthand_routes_options():
@app.options('/options') @app.options('/options')
def handler(request): def handler(request):
assert request.stream is None
return text('OK') return text('OK')
assert app.is_request_stream is False
request, response = app.test_client.options('/options') request, response = app.test_client.options('/options')
assert response.status == 200 assert response.status == 200