Blame SOURCES/0001-Add-support-for-Python-3.7.patch

32e5f0
From 2b83e7ccc12af9fec136e9f4897e1585b3b931aa Mon Sep 17 00:00:00 2001
32e5f0
From: Aymeric Augustin <aymeric.augustin@m4x.org>
32e5f0
Date: Thu, 24 May 2018 22:29:12 +0200
32e5f0
Subject: [PATCH 1/3] Add support for Python 3.7.
32e5f0
32e5f0
Hopefully for real this time.
32e5f0
32e5f0
This is annoyingly complicated.
32e5f0
32e5f0
Fix #405.
32e5f0
32e5f0
(cherry picked from commit 6f8f1c877744623f0a5df5917a85b97807bfb7e5)
32e5f0
---
32e5f0
 websockets/client.py                   | 24 +++++++----------
32e5f0
 websockets/py35/_test_client_server.py | 37 ++++++++++++++++++++++++++
32e5f0
 websockets/py35/client.py              | 33 +++++++++++++++++++++++
32e5f0
 websockets/py35/server.py              | 22 +++++++++++++++
32e5f0
 websockets/server.py                   | 25 +++++++----------
32e5f0
 websockets/test_client_server.py       |  1 +
32e5f0
 6 files changed, 111 insertions(+), 31 deletions(-)
32e5f0
 create mode 100644 websockets/py35/client.py
32e5f0
 create mode 100644 websockets/py35/server.py
32e5f0
32e5f0
diff --git a/websockets/client.py b/websockets/client.py
32e5f0
index 92f29e9..a86b90f 100644
32e5f0
--- a/websockets/client.py
32e5f0
+++ b/websockets/client.py
32e5f0
@@ -385,15 +385,7 @@ class Connect:
32e5f0
         self._creating_connection = loop.create_connection(
32e5f0
             factory, host, port, **kwds)
32e5f0
 
32e5f0
-    @asyncio.coroutine
32e5f0
-    def __aenter__(self):
32e5f0
-        return (yield from self)
32e5f0
-
32e5f0
-    @asyncio.coroutine
32e5f0
-    def __aexit__(self, exc_type, exc_value, traceback):
32e5f0
-        yield from self.ws_client.close()
32e5f0
-
32e5f0
-    def __await__(self):
32e5f0
+    def __iter__(self):                                     # pragma: no cover
32e5f0
         transport, protocol = yield from self._creating_connection
32e5f0
 
32e5f0
         try:
32e5f0
@@ -410,17 +402,19 @@ class Connect:
32e5f0
         self.ws_client = protocol
32e5f0
         return protocol
32e5f0
 
32e5f0
-    __iter__ = __await__
32e5f0
-
32e5f0
 
32e5f0
-# Disable asynchronous context manager functionality only on Python < 3.5.1
32e5f0
-# because it doesn't exist on Python < 3.5 and asyncio.ensure_future didn't
32e5f0
-# accept arbitrary awaitables in Python 3.5; that was fixed in Python 3.5.1.
32e5f0
+# We can't define __await__ on Python < 3.5.1 because asyncio.ensure_future
32e5f0
+# didn't accept arbitrary awaitables until Python 3.5.1. We don't define
32e5f0
+# __aenter__ and __aexit__ either on Python < 3.5.1 to keep things simple.
32e5f0
 if sys.version_info[:3] <= (3, 5, 0):                       # pragma: no cover
32e5f0
     @asyncio.coroutine
32e5f0
     def connect(*args, **kwds):
32e5f0
-        return Connect(*args, **kwds).__await__()
32e5f0
+        return Connect(*args, **kwds).__iter__()
32e5f0
     connect.__doc__ = Connect.__doc__
32e5f0
 
32e5f0
 else:
32e5f0
+    from .py35.client import __aenter__, __aexit__, __await__
32e5f0
+    Connect.__aenter__ = __aenter__
32e5f0
+    Connect.__aexit__ = __aexit__
32e5f0
+    Connect.__await__ = __await__
32e5f0
     connect = Connect
32e5f0
diff --git a/websockets/py35/_test_client_server.py b/websockets/py35/_test_client_server.py
32e5f0
index 4375248..5360d8d 100644
32e5f0
--- a/websockets/py35/_test_client_server.py
32e5f0
+++ b/websockets/py35/_test_client_server.py
32e5f0
@@ -13,6 +13,43 @@ from ..server import *
32e5f0
 from ..test_client_server import get_server_uri, handler
32e5f0
 
32e5f0
 
32e5f0
+class AsyncAwaitTests(unittest.TestCase):
32e5f0
+
32e5f0
+    def setUp(self):
32e5f0
+        self.loop = asyncio.new_event_loop()
32e5f0
+        asyncio.set_event_loop(self.loop)
32e5f0
+
32e5f0
+    def tearDown(self):
32e5f0
+        self.loop.close()
32e5f0
+
32e5f0
+    def test_client(self):
32e5f0
+        start_server = serve(handler, 'localhost', 0)
32e5f0
+        server = self.loop.run_until_complete(start_server)
32e5f0
+
32e5f0
+        async def run_client():
32e5f0
+            # Await connect.
32e5f0
+            client = await connect(get_server_uri(server))
32e5f0
+            self.assertEqual(client.state, State.OPEN)
32e5f0
+            await client.close()
32e5f0
+            self.assertEqual(client.state, State.CLOSED)
32e5f0
+
32e5f0
+        self.loop.run_until_complete(run_client())
32e5f0
+
32e5f0
+        server.close()
32e5f0
+        self.loop.run_until_complete(server.wait_closed())
32e5f0
+
32e5f0
+    def test_server(self):
32e5f0
+        async def run_server():
32e5f0
+            # Await serve.
32e5f0
+            server = await serve(handler, 'localhost', 0)
32e5f0
+            self.assertTrue(server.sockets)
32e5f0
+            server.close()
32e5f0
+            await server.wait_closed()
32e5f0
+            self.assertFalse(server.sockets)
32e5f0
+
32e5f0
+        self.loop.run_until_complete(run_server())
32e5f0
+
32e5f0
+
32e5f0
 class ContextManagerTests(unittest.TestCase):
32e5f0
 
32e5f0
     def setUp(self):
32e5f0
diff --git a/websockets/py35/client.py b/websockets/py35/client.py
32e5f0
new file mode 100644
32e5f0
index 0000000..7673ea3
32e5f0
--- /dev/null
32e5f0
+++ b/websockets/py35/client.py
32e5f0
@@ -0,0 +1,33 @@
32e5f0
+async def __aenter__(self):
32e5f0
+    return await self
32e5f0
+
32e5f0
+
32e5f0
+async def __aexit__(self, exc_type, exc_value, traceback):
32e5f0
+    await self.ws_client.close()
32e5f0
+
32e5f0
+
32e5f0
+async def __await_impl__(self):
32e5f0
+    # Duplicated with __iter__ because Python 3.7 requires an async function
32e5f0
+    # (as explained in __await__ below) which Python 3.4 doesn't support.
32e5f0
+    transport, protocol = await self._creating_connection
32e5f0
+
32e5f0
+    try:
32e5f0
+        await protocol.handshake(
32e5f0
+            self._wsuri, origin=self._origin,
32e5f0
+            available_extensions=protocol.available_extensions,
32e5f0
+            available_subprotocols=protocol.available_subprotocols,
32e5f0
+            extra_headers=protocol.extra_headers,
32e5f0
+        )
32e5f0
+    except Exception:
32e5f0
+        await protocol.fail_connection()
32e5f0
+        raise
32e5f0
+
32e5f0
+    self.ws_client = protocol
32e5f0
+    return protocol
32e5f0
+
32e5f0
+
32e5f0
+def __await__(self):
32e5f0
+    # __await__() must return a type that I don't know how to obtain except
32e5f0
+    # by calling __await__() on the return value of an async function.
32e5f0
+    # I'm not finding a better way to take advantage of PEP 492.
32e5f0
+    return __await_impl__(self).__await__()
32e5f0
diff --git a/websockets/py35/server.py b/websockets/py35/server.py
32e5f0
new file mode 100644
32e5f0
index 0000000..41a3675
32e5f0
--- /dev/null
32e5f0
+++ b/websockets/py35/server.py
32e5f0
@@ -0,0 +1,22 @@
32e5f0
+async def __aenter__(self):
32e5f0
+    return await self
32e5f0
+
32e5f0
+
32e5f0
+async def __aexit__(self, exc_type, exc_value, traceback):
32e5f0
+    self.ws_server.close()
32e5f0
+    await self.ws_server.wait_closed()
32e5f0
+
32e5f0
+
32e5f0
+async def __await_impl__(self):
32e5f0
+    # Duplicated with __iter__ because Python 3.7 requires an async function
32e5f0
+    # (as explained in __await__ below) which Python 3.4 doesn't support.
32e5f0
+    server = await self._creating_server
32e5f0
+    self.ws_server.wrap(server)
32e5f0
+    return self.ws_server
32e5f0
+
32e5f0
+
32e5f0
+def __await__(self):
32e5f0
+    # __await__() must return a type that I don't know how to obtain except
32e5f0
+    # by calling __await__() on the return value of an async function.
32e5f0
+    # I'm not finding a better way to take advantage of PEP 492.
32e5f0
+    return __await_impl__(self).__await__()
32e5f0
diff --git a/websockets/server.py b/websockets/server.py
32e5f0
index 8db0482..46c80dc 100644
32e5f0
--- a/websockets/server.py
32e5f0
+++ b/websockets/server.py
32e5f0
@@ -729,22 +729,11 @@ class Serve:
32e5f0
         self._creating_server = creating_server
32e5f0
         self.ws_server = ws_server
32e5f0
 
32e5f0
-    @asyncio.coroutine
32e5f0
-    def __aenter__(self):
32e5f0
-        return (yield from self)
32e5f0
-
32e5f0
-    @asyncio.coroutine
32e5f0
-    def __aexit__(self, exc_type, exc_value, traceback):
32e5f0
-        self.ws_server.close()
32e5f0
-        yield from self.ws_server.wait_closed()
32e5f0
-
32e5f0
-    def __await__(self):
32e5f0
+    def __iter__(self):                                     # pragma: no cover
32e5f0
         server = yield from self._creating_server
32e5f0
         self.ws_server.wrap(server)
32e5f0
         return self.ws_server
32e5f0
 
32e5f0
-    __iter__ = __await__
32e5f0
-
32e5f0
 
32e5f0
 def unix_serve(ws_handler, path, **kwargs):
32e5f0
     """
32e5f0
@@ -761,14 +750,18 @@ def unix_serve(ws_handler, path, **kwargs):
32e5f0
     return serve(ws_handler, path=path, **kwargs)
32e5f0
 
32e5f0
 
32e5f0
-# Disable asynchronous context manager functionality only on Python < 3.5.1
32e5f0
-# because it doesn't exist on Python < 3.5 and asyncio.ensure_future didn't
32e5f0
-# accept arbitrary awaitables in Python 3.5; that was fixed in Python 3.5.1.
32e5f0
+# We can't define __await__ on Python < 3.5.1 because asyncio.ensure_future
32e5f0
+# didn't accept arbitrary awaitables until Python 3.5.1. We don't define
32e5f0
+# __aenter__ and __aexit__ either on Python < 3.5.1 to keep things simple.
32e5f0
 if sys.version_info[:3] <= (3, 5, 0):                       # pragma: no cover
32e5f0
     @asyncio.coroutine
32e5f0
     def serve(*args, **kwds):
32e5f0
-        return Serve(*args, **kwds).__await__()
32e5f0
+        return Serve(*args, **kwds).__iter__()
32e5f0
     serve.__doc__ = Serve.__doc__
32e5f0
 
32e5f0
 else:
32e5f0
+    from .py35.server import __aenter__, __aexit__, __await__
32e5f0
+    Serve.__aenter__ = __aenter__
32e5f0
+    Serve.__aexit__ = __aexit__
32e5f0
+    Serve.__await__ = __await__
32e5f0
     serve = Serve
32e5f0
diff --git a/websockets/test_client_server.py b/websockets/test_client_server.py
32e5f0
index 8476913..27a2a71 100644
32e5f0
--- a/websockets/test_client_server.py
32e5f0
+++ b/websockets/test_client_server.py
32e5f0
@@ -1057,6 +1057,7 @@ class ClientServerOriginTests(unittest.TestCase):
32e5f0
 
32e5f0
 
32e5f0
 try:
32e5f0
+    from .py35._test_client_server import AsyncAwaitTests               # noqa
32e5f0
     from .py35._test_client_server import ContextManagerTests           # noqa
32e5f0
 except (SyntaxError, ImportError):                          # pragma: no cover
32e5f0
     pass
32e5f0
-- 
32e5f0
2.18.0
32e5f0