[asyncio] Support IPv6 addr type in DatagramProtocol.datagram_received#15543
[asyncio] Support IPv6 addr type in DatagramProtocol.datagram_received#15543sedat4ras wants to merge 1 commit intopython:mainfrom
Conversation
When using IPv6, the `addr` parameter passed to `datagram_received` is a 4-tuple `(host, port, flowinfo, scope_id)` of type `tuple[str, int, int, int]`, not a 2-tuple. Add this case to the union type so IPv6 datagram protocols can be properly typed without resorting to `Any`. Fixes python#15169
|
Diff from mypy_primer, showing the effect of this PR on open source code: anyio (https://github.com/agronholm/anyio)
+ src/anyio/_backends/_asyncio.py:1228: error: Argument 2 of "datagram_received" is incompatible with supertype "asyncio.protocols.DatagramProtocol"; supertype defines the argument type as "tuple[str | Any, int] | tuple[str, int, int, int]" [override]
+ src/anyio/_backends/_asyncio.py:1228: note: This violates the Liskov substitution principle
+ src/anyio/_backends/_asyncio.py:1228: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
|
|
The mypy_primer result shows that this change exposes a pre-existing Liskov Substitution Principle violation in This is arguably the correct behavior — widening the base class type correctly reveals that A few possible approaches if this regression is not acceptable:
Happy to take any direction the maintainers prefer! |
|
Please see the discussion in #15184 for why just widening the annotation won't work and what has been tried previously. |
|
Thanks for the pointer to #15184 — after reading the full discussion it's clear this hits the same fundamental limitation: subclasses like Closing since there's no clean solution until |
Fixes #15169
Changes
DatagramProtocol.datagram_receivedcurrently types theaddrparameter astuple[str | Any, int]— a 2-tuple — which handles IPv4 ((host, port)) and unusual protocols like AF_NETLINK. However, when using IPv6, the addr is a 4-tuple(host, port, flowinfo, scope_id), i.e.tuple[str, int, int, int].This adds the IPv6 4-tuple to the union type so that datagram protocols using IPv6 can be properly type-checked without resorting to
Anyor ignoring the error.Before:
After:
This is consistent with how IPv6 addresses are represented elsewhere in typeshed — for example,
socket.getaddrinfo()already usestuple[str, int, int, int]for IPv6 in its return type.