Repository: ethereum/web3.py

Issue:
Upgrade websockets to 10.1 ?
* Version: 5.25.0
* Python: 3.8
* OS: osx
* `pip freeze` output

```
solana==0.19.0 (problem)
```


### What was wrong?

Currently in dependency hell trying to use solana-py and web3 in same service. solana-py requires websockets 10.1, web3 seems to not support that. Below is the changelog for 10.1 release of websockets, there are no incompatible changes. Any chance I could bother the team to consider upgrading support to 10.1?

Also, from my logs it seems web3 needs "websockets<10" but i think changes were made to support 10.0 (#2175) . May need to update requirements:

remote:        The conflict is caused by:
remote:            solana 0.19.0 depends on websockets<11.0 and >=10.1
remote:            web3 5.25.0 depends on websockets<10 and >=9.1

https://websockets.readthedocs.io/en/latest/project/changelog.html#id3

Thanks!


### How can it be fixed?

Upgrade websockets support to 10.1

---
**Note:** We prefer to use issues to track our work. If you think you've encountered a bug in web3py or 
have a feature request, you're in the right place. If you have implementation or usage questions, 
please refer to our [documentation](https://web3py.readthedocs.io/en/latest/) and/or join the conversation 
on [discord](https://discord.gg/GHryRvPB84).



Discussion:
Yes please upgrade the requirement for `websocket` lib to support >= v10.0

Thank you.
+1 for this. Python 3.10 needs v10 `websocket` library.
+1 Also in dependency hell due to this one. If it's not easy to upgrade, is it possible to make in an optional dependency, e.g. web3[websockets] or web3[all] includes this dependency but otherwise excluded?
:eyes: Thanks for chiming in, everyone. It's on our list but it will be a little bit until we can get to it. If anyone has bandwidth to raise a PR in the meantime, we'd be happy to review. That's likely the fastest course of action. It looks like bumping to v10 results in a bunch of deprecation warnings around the `loop` parameter, but I haven't had time to dig into what the fix is for that. 
No bandwidth right now unfortunately, but we can push back our web3 integration to give you more time; may be more urgent for others. For reference: the relevant conflicts for us are the latest `uvicorn` ASGI server and the `cryptofeed` package. Both bumped to 10.x in recent versions and are critical to our stack.

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -90,7 +90,7 @@
         "requests>=2.16.0,<3.0.0",
         # remove typing_extensions after python_requires>=3.8, see web3._utils.compat
         "typing-extensions>=3.7.4.1,<5;python_version<'3.8'",
-        "websockets>=9.1,<10",
+        "websockets>=10.0.0,<11",
     ],
     python_requires='>=3.7,<3.10',
     extras_require=extras_require,
diff --git a/web3/providers/websocket.py b/web3/providers/websocket.py
--- a/web3/providers/websocket.py
+++ b/web3/providers/websocket.py
@@ -60,17 +60,16 @@ def get_default_endpoint() -> URI:
 class PersistentWebSocket:
 
     def __init__(
-        self, endpoint_uri: URI, loop: asyncio.AbstractEventLoop, websocket_kwargs: Any
+        self, endpoint_uri: URI, websocket_kwargs: Any
     ) -> None:
         self.ws: WebSocketClientProtocol = None
         self.endpoint_uri = endpoint_uri
-        self.loop = loop
         self.websocket_kwargs = websocket_kwargs
 
     async def __aenter__(self) -> WebSocketClientProtocol:
         if self.ws is None:
             self.ws = await connect(
-                uri=self.endpoint_uri, loop=self.loop, **self.websocket_kwargs
+                uri=self.endpoint_uri, **self.websocket_kwargs
             )
         return self.ws
 
@@ -113,7 +112,7 @@ def __init__(
                     'found: {1}'.format(RESTRICTED_WEBSOCKET_KWARGS, found_restricted_keys)
                 )
         self.conn = PersistentWebSocket(
-            self.endpoint_uri, WebsocketProvider._loop, websocket_kwargs
+            self.endpoint_uri, websocket_kwargs
         )
         super().__init__()
 


Test patch:
diff --git a/tests/core/providers/test_websocket_provider.py b/tests/core/providers/test_websocket_provider.py
--- a/tests/core/providers/test_websocket_provider.py
+++ b/tests/core/providers/test_websocket_provider.py
@@ -37,7 +37,9 @@ async def empty_server(websocket, path):
             data = await websocket.recv()
             await asyncio.sleep(0.02)
             await websocket.send(data)
-        server = websockets.serve(empty_server, '127.0.0.1', open_port, loop=event_loop)
+
+        asyncio.set_event_loop(event_loop)
+        server = websockets.serve(empty_server, '127.0.0.1', open_port)
         event_loop.run_until_complete(server)
         event_loop.run_forever()
 
@@ -54,7 +56,7 @@ def w3(open_port, start_websocket_server):
     # need new event loop as the one used by server is already running
     event_loop = asyncio.new_event_loop()
     endpoint_uri = 'ws://127.0.0.1:{}'.format(open_port)
-    event_loop.run_until_complete(wait_for_ws(endpoint_uri, event_loop))
+    event_loop.run_until_complete(wait_for_ws(endpoint_uri))
     provider = WebsocketProvider(endpoint_uri, websocket_timeout=0.01)
     return Web3(provider)
 
diff --git a/tests/integration/go_ethereum/test_goethereum_ws.py b/tests/integration/go_ethereum/test_goethereum_ws.py
--- a/tests/integration/go_ethereum/test_goethereum_ws.py
+++ b/tests/integration/go_ethereum/test_goethereum_ws.py
@@ -1,3 +1,4 @@
+import asyncio
 import pytest
 
 from tests.integration.common import (
@@ -63,8 +64,9 @@ def geth_command_arguments(geth_binary,
 
 
 @pytest.fixture(scope="module")
-def web3(geth_process, endpoint_uri, event_loop):
-    event_loop.run_until_complete(wait_for_ws(endpoint_uri, event_loop))
+def web3(geth_process, endpoint_uri):
+    event_loop = asyncio.new_event_loop()
+    event_loop.run_until_complete(wait_for_ws(endpoint_uri))
     _web3 = Web3(Web3.WebsocketProvider(endpoint_uri, websocket_timeout=30))
     return _web3
 
diff --git a/tests/utils.py b/tests/utils.py
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -13,11 +13,11 @@ def get_open_port():
     return str(port)
 
 
-async def wait_for_ws(endpoint_uri, event_loop, timeout=60):
+async def wait_for_ws(endpoint_uri, timeout=10):
     start = time.time()
     while time.time() < start + timeout:
         try:
-            async with websockets.connect(uri=endpoint_uri, loop=event_loop):
+            async with websockets.connect(uri=endpoint_uri):
                 pass
         except (ConnectionRefusedError, OSError):
             await asyncio.sleep(0.01)