python-websockets / websockets

Library for building WebSocket servers and clients in Python
https://websockets.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
5.16k stars 513 forks source link

fix: add `WebSocketClientProtocol` and `connect` to all for linters #1400

Closed Matthew-Burkard closed 1 year ago

Matthew-Burkard commented 1 year ago

With this linters and mypy work better with websockets when importing these such as:

from websockets.client import connect, WebSocketClientProtocol
aaugustin commented 1 year ago

Thank you for the proposal. When you say "work better", could you clarify what effect you observed?

Overall, it looks like the right thing to do here, but I'm curious to understand what it changes exactly.

If I adopt this solution, I will want to do it across all modules where a similar pattern exists.

Matthew-Burkard commented 1 year ago

If you import websockets and call websockets.connect like so:

import websockets

async def main() -> None:
    websocket = await websockets.connect("ws://localhost:8000/")

mypy raises the following error:

error: Module has no attribute "connect"  [attr-defined]
Found 1 error in 1 file (checked 1 source file)

If to avoid this you import connect from websockets.client as such:

from websockets.client import connect

async def main() -> None:
    websocket: WebSocketClientProtocol = await connect("ws://localhost:8000/")
    await websocket.close()

PyCharm builtin linter check for "Accessing a protected member of a class or a module" will flag that import since connect is not in __all__ for websockets.client module.

I want to add connect to __all__ for this reason and WebSocketClientProtocol for type annotation purposes, e.g.

websocket: WebSocketClientProtocol = ...

Doing this, in addition to satisfying the linter, enables auto-completions and go to source functionality within PyCharm.

aaugustin commented 1 year ago

This looks like an elegant and cheap solution to the issue described in #1385 (and several earlier issues). I'll look into it!

aaugustin commented 1 year ago

I fixed it with a slightly different approach in all modules where the issue could occur. I don't have PyCharm so I cannot confirm the fix.

aaugustin commented 1 year ago

(It doesn't help mypy understand websockets.connectconnect was already in websockets.__all__.)