Skip to content

Commit

Permalink
Merge branch 'master' into Improving-documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
ahopkins authored Oct 25, 2020
2 parents 12521cd + 4ca3e98 commit 634b586
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 19 deletions.
6 changes: 2 additions & 4 deletions examples/run_asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"""

from pathlib import Path
from sanic import Sanic, response

from sanic import Sanic, response

app = Sanic(__name__)

Expand Down Expand Up @@ -42,9 +42,7 @@ async def handler_file(request):

@app.route("/file_stream")
async def handler_file_stream(request):
return await response.file_stream(
Path("../") / "setup.py", chunk_size=1024
)
return await response.file_stream(Path("../") / "setup.py", chunk_size=1024)


@app.route("/stream", stream=True)
Expand Down
2 changes: 1 addition & 1 deletion sanic/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "20.9.0"
__version__ = "20.9.1"
2 changes: 2 additions & 0 deletions sanic/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ async def stream_callback(self, response: HTTPResponse) -> None:
if name not in (b"Set-Cookie",)
]

response.asgi = True

if "content-length" not in response.headers and not isinstance(
response, StreamingHTTPResponse
):
Expand Down
22 changes: 15 additions & 7 deletions sanic/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@


class BaseHTTPResponse:
def __init__(self):
self.asgi = False

def _encode_body(self, data):
return data.encode() if hasattr(data, "encode") else data

Expand Down Expand Up @@ -80,6 +83,8 @@ def __init__(
content_type="text/plain; charset=utf-8",
chunked=True,
):
super().__init__()

self.content_type = content_type
self.streaming_fn = streaming_fn
self.status = status
Expand Down Expand Up @@ -109,13 +114,14 @@ async def stream(
"""
if version != "1.1":
self.chunked = False
headers = self.get_headers(
version,
keep_alive=keep_alive,
keep_alive_timeout=keep_alive_timeout,
)
await self.protocol.push_data(headers)
await self.protocol.drain()
if not getattr(self, "asgi", False):
headers = self.get_headers(
version,
keep_alive=keep_alive,
keep_alive_timeout=keep_alive_timeout,
)
await self.protocol.push_data(headers)
await self.protocol.drain()
await self.streaming_fn(self)
if self.chunked:
await self.protocol.push_data(b"0\r\n\r\n")
Expand Down Expand Up @@ -143,6 +149,8 @@ def __init__(
content_type=None,
body_bytes=b"",
):
super().__init__()

self.content_type = content_type
self.body = body_bytes if body is None else self._encode_body(body)
self.status = status
Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ def open_local(paths, mode="r", encoding="utf8"):
ujson,
"aiofiles>=0.3.0",
"websockets>=8.1,<9.0",
"multidict>=4.0,<5.0",
"multidict==5.0.0",
"httpx==0.15.4",
]

tests_require = [
"pytest==5.2.1",
"multidict>=4.0,<5.0",
"multidict==5.0.0",
"gunicorn",
"pytest-cov",
"httpcore==0.3.0",
Expand All @@ -96,6 +96,7 @@ def open_local(paths, mode="r", encoding="utf8"):
"pytest-sanic",
"pytest-sugar",
"pytest-benchmark",
"pytest-dependency",
]

docs_require = [
Expand Down
11 changes: 6 additions & 5 deletions tests/test_load_module_from_file_location.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@pytest.fixture
def loaded_module_from_file_location():
return load_module_from_file_location(
str(Path(__file__).parent / "static/app_test_config.py")
str(Path(__file__).parent / "static" / "app_test_config.py")
)


Expand All @@ -20,10 +20,11 @@ def test_load_module_from_file_location(loaded_module_from_file_location):


@pytest.mark.dependency(depends=["test_load_module_from_file_location"])
def test_loaded_module_from_file_location_name(
loaded_module_from_file_location,
):
assert loaded_module_from_file_location.__name__ == "app_test_config"
def test_loaded_module_from_file_location_name(loaded_module_from_file_location,):
name = loaded_module_from_file_location.__name__
if "C:\\" in name:
name = name.split("\\")[-1]
assert name == "app_test_config"


def test_load_module_from_file_location_with_non_existing_env_variable():
Expand Down
16 changes: 16 additions & 0 deletions tests/test_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,29 @@ def test_chunked_streaming_returns_correct_content(streaming_app):
assert response.text == "foo,bar"


@pytest.mark.asyncio
async def test_chunked_streaming_returns_correct_content_asgi(streaming_app):
request, response = await streaming_app.asgi_client.get("/")
assert response.text == "4\r\nfoo,\r\n3\r\nbar\r\n0\r\n\r\n"


def test_non_chunked_streaming_adds_correct_headers(non_chunked_streaming_app):
request, response = non_chunked_streaming_app.test_client.get("/")
assert "Transfer-Encoding" not in response.headers
assert response.headers["Content-Type"] == "text/csv"
assert response.headers["Content-Length"] == "7"


@pytest.mark.asyncio
async def test_non_chunked_streaming_adds_correct_headers_asgi(
non_chunked_streaming_app,
):
request, response = await non_chunked_streaming_app.asgi_client.get("/")
assert "Transfer-Encoding" not in response.headers
assert response.headers["Content-Type"] == "text/csv"
assert response.headers["Content-Length"] == "7"


def test_non_chunked_streaming_returns_correct_content(
non_chunked_streaming_app,
):
Expand Down

0 comments on commit 634b586

Please sign in to comment.