Repository: tornadoweb/tornado
Pull request #2630 (2019-03-23 16:28:50)

Version 6.0.2


Patch:
diff --git a/docs/releases.rst b/docs/releases.rst
index f50e7826..1addf8c6 100644
--- a/docs/releases.rst
+++ b/docs/releases.rst
@@ -4,6 +4,7 @@ Release notes
 .. toctree::
    :maxdepth: 2
 
+   releases/v6.0.2
    releases/v6.0.1
    releases/v6.0.0
    releases/v5.1.1
diff --git a/docs/releases/v6.0.2.rst b/docs/releases/v6.0.2.rst
new file mode 100644
index 00000000..3d394a3e
--- /dev/null
+++ b/docs/releases/v6.0.2.rst
@@ -0,0 +1,13 @@
+What's new in Tornado 6.0.2
+===========================
+
+Mar 23, 2019
+------------
+
+Bug fixes
+~~~~~~~~~
+
+- `.WebSocketHandler.set_nodelay` works again.
+- Accessing ``HTTPResponse.body`` now returns an empty byte string
+  instead of raising ``ValueError`` for error responses that don't
+  have a body (it returned None in this case in Tornado 5).
diff --git a/tornado/__init__.py b/tornado/__init__.py
index 1050a114..bc5dbb91 100644
--- a/tornado/__init__.py
+++ b/tornado/__init__.py
@@ -22,5 +22,5 @@
 # is zero for an official release, positive for a development branch,
 # or negative for a release candidate or beta (after the base version
 # number has been incremented)
-version = "6.0.1"
-version_info = (6, 0, 1, 0)
+version = "6.0.2"
+version_info = (6, 0, 2, 0)
diff --git a/tornado/httpclient.py b/tornado/httpclient.py
index 33abe2e1..882600af 100644
--- a/tornado/httpclient.py
+++ b/tornado/httpclient.py
@@ -665,7 +665,7 @@ class HTTPResponse(object):
     @property
     def body(self) -> bytes:
         if self.buffer is None:
-            raise ValueError("body not set")
+            return b""
         elif self._body is None:
             self._body = self.buffer.getvalue()
 
diff --git a/tornado/websocket.py b/tornado/websocket.py
index 00d08bab..d991fee5 100644
--- a/tornado/websocket.py
+++ b/tornado/websocket.py
@@ -558,8 +558,8 @@ class WebSocketHandler(tornado.web.RequestHandler):
 
         .. versionadded:: 3.1
         """
-        assert self.stream is not None
-        self.stream.set_nodelay(value)
+        assert self.ws_connection is not None
+        self.ws_connection.set_nodelay(value)
 
     def on_connection_close(self) -> None:
         if self.ws_connection:
@@ -714,6 +714,10 @@ class WebSocketProtocol(abc.ABC):
     async def _receive_frame_loop(self) -> None:
         raise NotImplementedError()
 
+    @abc.abstractmethod
+    def set_nodelay(self, x: bool) -> None:
+        raise NotImplementedError()
+
 
 class _PerMessageDeflateCompressor(object):
     def __init__(
@@ -1345,6 +1349,9 @@ class WebSocketProtocol13(WebSocketProtocol):
         self.write_ping(b"")
         self.last_ping = now
 
+    def set_nodelay(self, x: bool) -> None:
+        self.stream.set_nodelay(x)
+
 
 class WebSocketClientConnection(simple_httpclient._HTTPConnection):
     """WebSocket client connection.


Test patch:
diff --git a/tornado/test/websocket_test.py b/tornado/test/websocket_test.py
index 715ecf1e..d4b7a741 100644
--- a/tornado/test/websocket_test.py
+++ b/tornado/test/websocket_test.py
@@ -198,6 +198,12 @@ class ErrorInAsyncOpenHandler(TestWebSocketHandler):
         raise Exception("boom")
 
 
+class NoDelayHandler(TestWebSocketHandler):
+    def open(self):
+        self.set_nodelay(True)
+        self.write_message("hello")
+
+
 class WebSocketBaseTestCase(AsyncHTTPTestCase):
     @gen.coroutine
     def ws_connect(self, path, **kwargs):
@@ -258,6 +264,7 @@ class WebSocketTest(WebSocketBaseTestCase):
                 ),
                 ("/error_in_open", ErrorInOpenHandler),
                 ("/error_in_async_open", ErrorInAsyncOpenHandler),
+                ("/nodelay", NoDelayHandler),
             ],
             template_loader=DictLoader({"message.html": "<b>{{ message }}</b>"}),
         )
@@ -562,6 +569,12 @@ class WebSocketTest(WebSocketBaseTestCase):
             res = yield ws.read_message()
         self.assertIsNone(res)
 
+    @gen_test
+    def test_nodelay(self):
+        ws = yield self.ws_connect("/nodelay")
+        res = yield ws.read_message()
+        self.assertEqual(res, "hello")
+
 
 class NativeCoroutineOnMessageHandler(TestWebSocketHandler):
     def initialize(self, **kwargs):