Skip to content

Conversation

@mdalp
Copy link
Contributor

@mdalp mdalp commented Sep 2, 2025

What was wrong?

Importing from web3 import Web3 was causing a DeprecationWarning to be raised.
This can be easily replicated by doing:

$ pytest tests/core/providers/test_legacy_websocket_provider.py -W error::DeprecationWarning
ImportError while loading conftest '/Users/mdalp/coding/web3.py/conftest.py'.
conftest.py:7: in <module>
    from tests.utils import (
tests/utils.py:8: in <module>
    from websockets.legacy.client import (
.venv/lib/python3.13/site-packages/websockets/legacy/__init__.py:6: in <module>
    warnings.warn(  # deprecated in 14.0 - 2024-11-09
E   DeprecationWarning: websockets.legacy is deprecated; see https://websockets.readthedocs.io/en/stable/howto/upgrade.html for upgrade instructions

This PR aims at resolving that once for all.

How was it fixed?

  1. lazy loading websockets.legacy in the legacy provider
  2. using the recommended implementation from the websockets package
  3. running tests to ensure they still pass

Todo:

  • Clean up commit history
  • Add or update documentation related to these changes
  • Add entry to the release notes

Notes:

The pre-commit hook changed quite a lot the file, I ended up committing those changes in a separate commit so that the relevant changes can be seen in isolation.

Cute Animal Picture

Cute baby xenomorph

Copy link
Collaborator

@kclowes kclowes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR! This is an (admittedly pretty small) breaking change with the type from WebSocketClientProtocol -> ClientConnection, so we'll need to wait until v8 to get this in. I am going to start working on v8 changes in the next few weeks, so will be able to get these changes in then. I left a couple comments that I can either address when I pull it in under v8, or if you want/have bandwidth to update, feel free!

I didn't know that you could use the Union | before Python 3.10, that's awesome!

async def _provider_specific_disconnect(self) -> None:
# this should remain idempotent
if self._ws is not None and not self._ws.closed:
if self._ws is not None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still need to figure out how to check for self._ws.closed, even if it's not that same method name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, I did check this and I found out that self._ws.close() is idempotent already, what I didn't realise though is that web3.py still supports websockets >=10.0,<13.0, meaning me importing directly from websockets.asyncio would break that compatibility.
So I would need to rework my PR to take that into account.

I also noticed this issue #3679 which plans to move websockets bottom pin to >=14 #3530, which would essentially remove this problem completely.
Should I just do that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could either go down the path of supporting all the variations (aka <13; >=13,<14; >=14), i.e.

import websockets
websockets_version = tuple(int(x) for x in websockets.__version__.split(".") if x.isdigit())

if websockets_version < (13, 0):
    from websockets.legacy.client import (
        WebSocketClientProtocol as ClientConnection,  # we are safe to steal the name as the scope of interface we use is the same
        connect,
    )
else:
    # python3.8 supports up to version 13,
    # which does not default to the asyncio implementation yet.
    # For this reason connect and ClientConnection need to be imported
    # from asyncio.client explicitly.
    # When web3.py stops supporting python3.8,
    # it'll be possible to use `from websockets import connect, ClientConnection`.
    from websockets.asyncio.client import (
        ClientConnection,
        connect,
    )

or simply drop support for at least version <13.

Given the amount of usage of the websockets library interface either solution is fine, not a big deal.

@kclowes kclowes added the v8 breaking changes for v8 label Sep 12, 2025
@mdalp
Copy link
Contributor Author

mdalp commented Sep 15, 2025

Hey @kclowes ! I agree this is a potentially breaking change, we might even not need it in this shape, depending on when it is planned to sunset the legacy_websocket provider implementation. But definitely it makes sense to wait until v8.

About your comments, I can definitely take care of them 💪 , thanks for those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v8 breaking changes for v8

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants