diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index f1062a8cd052a5..0a9f897463b2f8 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1480,6 +1480,10 @@ def with_hostmask(self): def is_unspecified(self): return self._ip == 0 and self.network.is_unspecified + @property + def is_loopback(self): + return super().is_loopback and self.network.is_loopback + class IPv4Network(_BaseV4, _BaseNetwork): diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 3f017b97dc28a3..3f84592a31d467 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -2307,6 +2307,10 @@ def testReservedIpv4(self): self.assertFalse(ipaddress.ip_interface('0.0.0.0/31').is_unspecified) self.assertFalse(ipaddress.ip_interface('1.2.3.4/32').is_unspecified) + self.assertTrue(ipaddress.ip_interface('127.0.0.1/8').is_loopback) + self.assertFalse(ipaddress.ip_interface('127.0.0.1/4').is_loopback) + self.assertFalse(ipaddress.ip_interface('1.2.3.4/32').is_loopback) + self.assertEqual(True, ipaddress.ip_interface( '192.168.1.1/17').is_private) self.assertEqual(False, ipaddress.ip_network('192.169.0.0').is_private) diff --git a/Misc/NEWS.d/next/Library/2026-06-20-21-40-02.gh-issue-151785.YkmPlX.rst b/Misc/NEWS.d/next/Library/2026-06-20-21-40-02.gh-issue-151785.YkmPlX.rst new file mode 100644 index 00000000000000..b04754bb99ef36 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-20-21-40-02.gh-issue-151785.YkmPlX.rst @@ -0,0 +1,2 @@ +Fix :attr:`!ipaddress.IPv4Interface.is_loopback` to also consider the +interface's network, matching :class:`ipaddress.IPv6Interface`.