From fa5a4fcd2a9c02036bad5af24c2ede40a9dc62ee Mon Sep 17 00:00:00 2001 From: Anders Bruihler <6530276+ABruihler@users.noreply.github.com> Date: Wed, 26 Aug 2026 15:44:01 -0400 Subject: [PATCH 1/4] Annotate 3.14+ ipaddress `version` / `max_prefixlen` as `Literal` Declared as bare `Final`, they infer as `int`, so `.version` no longer narrows an `IPv4Network | IPv6Network` union the way the pre-3.14 `Literal`-returning properties did. Co-Authored-By: Claude Opus 5 (1M context) --- stdlib/ipaddress.pyi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/ipaddress.pyi b/stdlib/ipaddress.pyi index c514abfa569f..e8c025d170df 100644 --- a/stdlib/ipaddress.pyi +++ b/stdlib/ipaddress.pyi @@ -109,8 +109,8 @@ class _BaseNetwork(_IPAddressBase, Generic[_A]): class _BaseV4: __slots__ = () if sys.version_info >= (3, 14): - version: Final = 4 - max_prefixlen: Final = 32 + version: Final[Literal[4]] = 4 + max_prefixlen: Final[Literal[32]] = 32 else: @property def version(self) -> Literal[4]: ... @@ -162,8 +162,8 @@ class IPv4Interface(IPv4Address): class _BaseV6: __slots__ = () if sys.version_info >= (3, 14): - version: Final = 6 - max_prefixlen: Final = 128 + version: Final[Literal[6]] = 6 + max_prefixlen: Final[Literal[128]] = 128 else: @property def version(self) -> Literal[6]: ... From 0752a116c67a104a36a74855ba5430aa46902bfc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 19:46:48 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/ipaddress.pyi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/ipaddress.pyi b/stdlib/ipaddress.pyi index e8c025d170df..c514abfa569f 100644 --- a/stdlib/ipaddress.pyi +++ b/stdlib/ipaddress.pyi @@ -109,8 +109,8 @@ class _BaseNetwork(_IPAddressBase, Generic[_A]): class _BaseV4: __slots__ = () if sys.version_info >= (3, 14): - version: Final[Literal[4]] = 4 - max_prefixlen: Final[Literal[32]] = 32 + version: Final = 4 + max_prefixlen: Final = 32 else: @property def version(self) -> Literal[4]: ... @@ -162,8 +162,8 @@ class IPv4Interface(IPv4Address): class _BaseV6: __slots__ = () if sys.version_info >= (3, 14): - version: Final[Literal[6]] = 6 - max_prefixlen: Final[Literal[128]] = 128 + version: Final = 6 + max_prefixlen: Final = 128 else: @property def version(self) -> Literal[6]: ... From 44bc4e1a16a42faa4b1bd1c7e25e337bb47311ef Mon Sep 17 00:00:00 2001 From: Anders Bruihler <6530276+ABruihler@users.noreply.github.com> Date: Wed, 26 Aug 2026 16:00:12 -0400 Subject: [PATCH 3/4] Revert "[pre-commit.ci] auto fixes from pre-commit.com hooks" This reverts commit 0752a116c. PYI064's autofix rewrites `Final[Literal[4]] = 4` to a bare `Final`, which is exactly the form that loses the declared literal type, so the fix undoes itself. Co-Authored-By: Claude Opus 5 (1M context) --- stdlib/ipaddress.pyi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/ipaddress.pyi b/stdlib/ipaddress.pyi index c514abfa569f..e8c025d170df 100644 --- a/stdlib/ipaddress.pyi +++ b/stdlib/ipaddress.pyi @@ -109,8 +109,8 @@ class _BaseNetwork(_IPAddressBase, Generic[_A]): class _BaseV4: __slots__ = () if sys.version_info >= (3, 14): - version: Final = 4 - max_prefixlen: Final = 32 + version: Final[Literal[4]] = 4 + max_prefixlen: Final[Literal[32]] = 32 else: @property def version(self) -> Literal[4]: ... @@ -162,8 +162,8 @@ class IPv4Interface(IPv4Address): class _BaseV6: __slots__ = () if sys.version_info >= (3, 14): - version: Final = 6 - max_prefixlen: Final = 128 + version: Final[Literal[6]] = 6 + max_prefixlen: Final[Literal[128]] = 128 else: @property def version(self) -> Literal[6]: ... From 5bd8c2331e10af40f9c10eff2013ed6cb107448d Mon Sep 17 00:00:00 2001 From: Anders Bruihler <6530276+ABruihler@users.noreply.github.com> Date: Wed, 26 Aug 2026 16:00:47 -0400 Subject: [PATCH 4/4] Silence PYI064 on the explicit `Literal` annotations The rule's suggested bare `Final` is the form that loses the declared literal type, so it cannot apply here. Co-Authored-By: Claude Opus 5 (1M context) --- stdlib/ipaddress.pyi | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stdlib/ipaddress.pyi b/stdlib/ipaddress.pyi index e8c025d170df..c492a472da41 100644 --- a/stdlib/ipaddress.pyi +++ b/stdlib/ipaddress.pyi @@ -109,8 +109,10 @@ class _BaseNetwork(_IPAddressBase, Generic[_A]): class _BaseV4: __slots__ = () if sys.version_info >= (3, 14): - version: Final[Literal[4]] = 4 - max_prefixlen: Final[Literal[32]] = 32 + # a bare `Final` infers as `int`, which cannot narrow an + # `IPv4Network | IPv6Network` union (PYI064 does not account for that) + version: Final[Literal[4]] = 4 # noqa: PYI064 + max_prefixlen: Final[Literal[32]] = 32 # noqa: PYI064 else: @property def version(self) -> Literal[4]: ... @@ -162,8 +164,10 @@ class IPv4Interface(IPv4Address): class _BaseV6: __slots__ = () if sys.version_info >= (3, 14): - version: Final[Literal[6]] = 6 - max_prefixlen: Final[Literal[128]] = 128 + # a bare `Final` infers as `int`, which cannot narrow an + # `IPv4Network | IPv6Network` union (PYI064 does not account for that) + version: Final[Literal[6]] = 6 # noqa: PYI064 + max_prefixlen: Final[Literal[128]] = 128 # noqa: PYI064 else: @property def version(self) -> Literal[6]: ...