From 0530a85e1d83fe0018dfa4dce8f0545f20481568 Mon Sep 17 00:00:00 2001 From: ANSHUL SINGH <72524975+ekanshul@users.noreply.github.com> Date: Sun, 16 Aug 2026 14:14:59 +0530 Subject: [PATCH] asyncio: allow port=None in create_server when a host is given create_server passes port straight to getaddrinfo, which accepts None, so create_server(proto, "localhost", None) works at runtime but the stub rejected it because the non-sock overload declared port: int. Widen that parameter to int | None in the six create_server overloads (three version gates each in base_events.pyi and events.pyi) and add test cases covering the host/port/sock combinations. create_connection also has port: int = ..., but it is left alone here: its port is not optional in the same way. Co-Authored-By: Claude Opus 5 (1M context) --- .../test_cases/asyncio/check_create_server.py | 30 +++++++++++++++++++ stdlib/asyncio/base_events.pyi | 6 ++-- stdlib/asyncio/events.pyi | 6 ++-- 3 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 stdlib/@tests/test_cases/asyncio/check_create_server.py diff --git a/stdlib/@tests/test_cases/asyncio/check_create_server.py b/stdlib/@tests/test_cases/asyncio/check_create_server.py new file mode 100644 index 000000000000..8d3955cfcf37 --- /dev/null +++ b/stdlib/@tests/test_cases/asyncio/check_create_server.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +import asyncio +import socket +from typing_extensions import assert_type + + +async def check_create_server(loop: asyncio.AbstractEventLoop, base_loop: asyncio.BaseEventLoop) -> None: + # `port` is optional whenever a host is given: the runtime passes it straight + # to getaddrinfo, which treats None as "any port". + assert_type(await loop.create_server(asyncio.Protocol, "localhost"), asyncio.Server) + assert_type(await loop.create_server(asyncio.Protocol, "localhost", 8080), asyncio.Server) + assert_type(await loop.create_server(asyncio.Protocol, "localhost", None), asyncio.Server) + assert_type(await loop.create_server(asyncio.Protocol, ["localhost", "127.0.0.1"], 8080), asyncio.Server) + + # A port with no host binds every interface. + assert_type(await loop.create_server(asyncio.Protocol, None, 8080), asyncio.Server) + assert_type(await loop.create_server(asyncio.Protocol, port=8080), asyncio.Server) + + assert_type(await base_loop.create_server(asyncio.Protocol, "localhost", None), asyncio.Server) + assert_type(await base_loop.create_server(asyncio.Protocol, port=8080), asyncio.Server) + + +async def check_create_server_sock(loop: asyncio.AbstractEventLoop, sock: socket.socket) -> None: + assert_type(await loop.create_server(asyncio.Protocol, sock=sock), asyncio.Server) + + # The runtime rejects host/port together with sock: + # ValueError: host/port and sock can not be specified at the same time + await loop.create_server(asyncio.Protocol, "localhost", sock=sock) # type: ignore + await loop.create_server(asyncio.Protocol, None, 8080, sock=sock) # type: ignore diff --git a/stdlib/asyncio/base_events.pyi b/stdlib/asyncio/base_events.pyi index 056d9a2d36c9..ffd42bd70818 100644 --- a/stdlib/asyncio/base_events.pyi +++ b/stdlib/asyncio/base_events.pyi @@ -244,7 +244,7 @@ class BaseEventLoop(AbstractEventLoop): self, protocol_factory: _ProtocolFactory, host: str | Sequence[str] | None = None, - port: int = ..., + port: int | None = None, *, family: int = 0, flags: int = 1, @@ -283,7 +283,7 @@ class BaseEventLoop(AbstractEventLoop): self, protocol_factory: _ProtocolFactory, host: str | Sequence[str] | None = None, - port: int = ..., + port: int | None = None, *, family: int = AddressFamily.AF_UNSPEC, flags: int = AddressInfo.AI_PASSIVE, @@ -320,7 +320,7 @@ class BaseEventLoop(AbstractEventLoop): self, protocol_factory: _ProtocolFactory, host: str | Sequence[str] | None = None, - port: int = ..., + port: int | None = None, *, family: int = AddressFamily.AF_UNSPEC, flags: int = AddressInfo.AI_PASSIVE, diff --git a/stdlib/asyncio/events.pyi b/stdlib/asyncio/events.pyi index 12978a97679f..7d596959acd6 100644 --- a/stdlib/asyncio/events.pyi +++ b/stdlib/asyncio/events.pyi @@ -299,7 +299,7 @@ class AbstractEventLoop: self, protocol_factory: _ProtocolFactory, host: str | Sequence[str] | None = None, - port: int = ..., + port: int | None = None, *, family: int = AddressFamily.AF_UNSPEC, flags: int = AddressInfo.AI_PASSIVE, @@ -340,7 +340,7 @@ class AbstractEventLoop: self, protocol_factory: _ProtocolFactory, host: str | Sequence[str] | None = None, - port: int = ..., + port: int | None = None, *, family: int = AddressFamily.AF_UNSPEC, flags: int = AddressInfo.AI_PASSIVE, @@ -379,7 +379,7 @@ class AbstractEventLoop: self, protocol_factory: _ProtocolFactory, host: str | Sequence[str] | None = None, - port: int = ..., + port: int | None = None, *, family: int = AddressFamily.AF_UNSPEC, flags: int = AddressInfo.AI_PASSIVE,