diff --git a/sanic/app.py b/sanic/app.py index a02b40fa..cf4807d0 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -63,9 +63,14 @@ class Sanic: frame_records = stack()[1] name = getmodulename(frame_records[1]) # Check for unsupported function on custom request objects - if request_class and any(hasattr(request_class, m) for m in ( - "body_init", "body_push", "body_finish" - )) and request_class.receive_body is Request.receive_body: + if ( + request_class + and any( + hasattr(request_class, m) + for m in ("body_init", "body_push", "body_finish") + ) + and request_class.receive_body is Request.receive_body + ): raise NotImplementedError( "Request methods body_init, body_push and body_finish " f"are no longer supported. {request_class!r} should " diff --git a/sanic/compat.py b/sanic/compat.py index 4e4094be..99e0127e 100644 --- a/sanic/compat.py +++ b/sanic/compat.py @@ -5,11 +5,11 @@ from multidict import CIMultiDict # type: ignore try: - from trio import Cancelled + from trio import Cancelled # type: ignore - CancelledErrors = CancelledError, Cancelled + CancelledErrors = [CancelledError, Cancelled] except ImportError: - CancelledErrors = (CancelledError,) + CancelledErrors = [CancelledError] class Header(CIMultiDict): diff --git a/sanic/http.py b/sanic/http.py index 6049d3b8..8aaa4aa0 100644 --- a/sanic/http.py +++ b/sanic/http.py @@ -179,7 +179,7 @@ class Http: self.stage = Stage.HANDLER self.request = request - async def http1_response_header(self, data, end_stream) -> bytes: + async def http1_response_header(self, data, end_stream): res = self.response # Compatibility with simple response body if not data and getattr(res, "body", None): @@ -244,22 +244,22 @@ class Http: self.response_func = None self.stage = Stage.IDLE - async def http1_response_chunked(self, data, end_stream) -> bytes: + async def http1_response_chunked(self, data, end_stream): """Format a part of response body in chunked encoding.""" # Chunked encoding size = len(data) if end_stream: await self._send( b"%x\r\n%b\r\n0\r\n\r\n" % (size, data) - if size else - b"0\r\n\r\n" + if size + else b"0\r\n\r\n" ) self.response_func = None self.stage = Stage.IDLE elif size: await self._send(b"%x\r\n%b\r\n" % (size, data)) - async def http1_response_normal(self, data: bytes, end_stream: bool) -> bytes: + async def http1_response_normal(self, data: bytes, end_stream: bool): """Format / keep track of non-chunked response.""" bytes_left = self.response_bytes_left - len(data) if bytes_left <= 0: diff --git a/sanic/request.py b/sanic/request.py index e211629c..bc7a548b 100644 --- a/sanic/request.py +++ b/sanic/request.py @@ -132,24 +132,17 @@ class Request: ) return response - async def receive_body(self): - self.body = b"".join([data async for data in self.stream]) - async def receive_body(self): """Receive request.body, if not already received. - Streaming handlers may call this to receive the full body. + Streaming handlers may call this to receive the full body. Sanic calls + this function before running any handlers of non-streaming routes. - This is added as a compatibility shim in Sanic 20.3 because future - versions of Sanic will make all requests streaming and will use this - function instead of the non-async body_init/push/finish functions. - - Please make an issue if your code depends on the old functionality and - cannot be upgraded to the new API. + Custom request classes can override this for custom handling of both + streaming and non-streaming routes. """ - if not self.stream: - return - self.body = b"".join([data async for data in self.stream]) + if not self.body: + self.body = b"".join([data async for data in self.stream]) @property def json(self):