From 08b3c03d050f81023171996d5d55ffee956682de Mon Sep 17 00:00:00 2001 From: Bonu Krishna Chaitanya Date: Fri, 14 Nov 2025 10:38:47 +0530 Subject: [PATCH 01/10] make hosts an `iterable` --- Lib/ipaddress.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index aa0cf4a0620cd0..bc9499cb5e2415 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1546,7 +1546,7 @@ def __init__(self, address, strict=True): if self._prefixlen == (self.max_prefixlen - 1): self.hosts = self.__iter__ elif self._prefixlen == (self.max_prefixlen): - self.hosts = lambda: [IPv4Address(addr)] + self.hosts = lambda: iter([IPv4Address(addr)]) @property @functools.lru_cache() @@ -2337,7 +2337,7 @@ def __init__(self, address, strict=True): if self._prefixlen == (self.max_prefixlen - 1): self.hosts = self.__iter__ elif self._prefixlen == self.max_prefixlen: - self.hosts = lambda: [IPv6Address(addr)] + self.hosts = lambda: iter([IPv6Address(addr)]) def hosts(self): """Generate Iterator over usable hosts in a network. From f7c18032401b533a664a26afee5154dde6842cb9 Mon Sep 17 00:00:00 2001 From: Bonu Krishna Chaitanya Date: Fri, 14 Nov 2025 16:15:49 +0530 Subject: [PATCH 02/10] code review changes --- Lib/ipaddress.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index bc9499cb5e2415..f1062a8cd052a5 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1546,7 +1546,7 @@ def __init__(self, address, strict=True): if self._prefixlen == (self.max_prefixlen - 1): self.hosts = self.__iter__ elif self._prefixlen == (self.max_prefixlen): - self.hosts = lambda: iter([IPv4Address(addr)]) + self.hosts = lambda: iter((IPv4Address(addr),)) @property @functools.lru_cache() @@ -2337,7 +2337,7 @@ def __init__(self, address, strict=True): if self._prefixlen == (self.max_prefixlen - 1): self.hosts = self.__iter__ elif self._prefixlen == self.max_prefixlen: - self.hosts = lambda: iter([IPv6Address(addr)]) + self.hosts = lambda: iter((IPv6Address(addr),)) def hosts(self): """Generate Iterator over usable hosts in a network. From dd8d1f2f719582cff8dfc4586514dc6cf2c75145 Mon Sep 17 00:00:00 2001 From: Bonu Krishna Chaitanya Date: Fri, 14 Nov 2025 16:16:02 +0530 Subject: [PATCH 03/10] tests --- Lib/test/test_ipaddress.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 11721a59972672..554ba1edc4b040 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -13,6 +13,7 @@ import ipaddress import weakref from test.support import LARGEST, SMALLEST +from typing import Iterator class BaseTestCase(unittest.TestCase): @@ -1472,12 +1473,16 @@ def testGetSupernet4(self): self.ipv6_scoped_network.supernet(new_prefix=62)) def testHosts(self): + hosts = self.ipv4_network.hosts() + self.assertIsInstance(hosts, Iterator) hosts = list(self.ipv4_network.hosts()) self.assertEqual(254, len(hosts)) self.assertEqual(ipaddress.IPv4Address('1.2.3.1'), hosts[0]) self.assertEqual(ipaddress.IPv4Address('1.2.3.254'), hosts[-1]) ipv6_network = ipaddress.IPv6Network('2001:658:22a:cafe::/120') + hosts = ipv6_network.hosts() + self.assertIsInstance(hosts, Iterator) hosts = list(ipv6_network.hosts()) self.assertEqual(255, len(hosts)) self.assertEqual(ipaddress.IPv6Address('2001:658:22a:cafe::1'), hosts[0]) From 17a1a05d566cd7ef1be872a9c6f90c2705b27ad6 Mon Sep 17 00:00:00 2001 From: Bonu Krishna Chaitanya Date: Fri, 14 Nov 2025 16:29:52 +0530 Subject: [PATCH 04/10] news entry --- .../next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst diff --git a/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst b/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst new file mode 100644 index 00000000000000..0bedc0522e85d4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst @@ -0,0 +1,2 @@ +In :mod:`ipaddress`, ensure that the methods ``IPv6Network.hosts()`` and +``IPv4Network.hosts()`` always returns an iterator. From 54043df19ec4b1652393e193dd71069c06687d6c Mon Sep 17 00:00:00 2001 From: Bonu Krishna Chaitanya Date: Fri, 14 Nov 2025 18:55:06 +0530 Subject: [PATCH 05/10] more tests --- Lib/test/test_ipaddress.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 554ba1edc4b040..451d145df8ede5 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -1508,6 +1508,8 @@ def testHosts(self): addrs = [ipaddress.IPv4Address('1.2.3.4')] str_args = '1.2.3.4/32' tpl_args = ('1.2.3.4', 32) + self.assertIsInstance(ipaddress.ip_network(str_args).hosts(), Iterator) + self.assertIsInstance(ipaddress.ip_network(tpl_args).hosts(), Iterator) self.assertEqual(addrs, list(ipaddress.ip_network(str_args).hosts())) self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), @@ -1517,6 +1519,8 @@ def testHosts(self): ipaddress.IPv6Address('2001:658:22a:cafe::1')] str_args = '2001:658:22a:cafe::/127' tpl_args = ('2001:658:22a:cafe::', 127) + self.assertIsInstance(ipaddress.ip_network(str_args).hosts(), Iterator) + self.assertIsInstance(ipaddress.ip_network(tpl_args).hosts(), Iterator) self.assertEqual(addrs, list(ipaddress.ip_network(str_args).hosts())) self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), From cee691ac5caff7c06927a3bbf3043ea1f6b31c7c Mon Sep 17 00:00:00 2001 From: Bonu Krishna Chaitanya Date: Sat, 15 Nov 2025 19:31:11 +0530 Subject: [PATCH 06/10] more tests --- Lib/test/test_ipaddress.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 451d145df8ede5..b424055ebb31b4 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -13,7 +13,7 @@ import ipaddress import weakref from test.support import LARGEST, SMALLEST -from typing import Iterator +from collections.abc import Iterator class BaseTestCase(unittest.TestCase): @@ -1475,6 +1475,7 @@ def testGetSupernet4(self): def testHosts(self): hosts = self.ipv4_network.hosts() self.assertIsInstance(hosts, Iterator) + self.assertIsNotNone(next(hosts)) hosts = list(self.ipv4_network.hosts()) self.assertEqual(254, len(hosts)) self.assertEqual(ipaddress.IPv4Address('1.2.3.1'), hosts[0]) @@ -1483,6 +1484,7 @@ def testHosts(self): ipv6_network = ipaddress.IPv6Network('2001:658:22a:cafe::/120') hosts = ipv6_network.hosts() self.assertIsInstance(hosts, Iterator) + self.assertIsNotNone(next(hosts)) hosts = list(ipv6_network.hosts()) self.assertEqual(255, len(hosts)) self.assertEqual(ipaddress.IPv6Address('2001:658:22a:cafe::1'), hosts[0]) @@ -1510,6 +1512,10 @@ def testHosts(self): tpl_args = ('1.2.3.4', 32) self.assertIsInstance(ipaddress.ip_network(str_args).hosts(), Iterator) self.assertIsInstance(ipaddress.ip_network(tpl_args).hosts(), Iterator) + hosts = ipaddress.ip_network(str_args).hosts() + self.assertIsNotNone(next(hosts)) + hosts = ipaddress.ip_network(tpl_args).hosts() + self.assertIsNotNone(next(hosts)) self.assertEqual(addrs, list(ipaddress.ip_network(str_args).hosts())) self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), @@ -1521,6 +1527,10 @@ def testHosts(self): tpl_args = ('2001:658:22a:cafe::', 127) self.assertIsInstance(ipaddress.ip_network(str_args).hosts(), Iterator) self.assertIsInstance(ipaddress.ip_network(tpl_args).hosts(), Iterator) + hosts = ipaddress.ip_network(str_args).hosts() + self.assertIsNotNone(next(hosts)) + hosts = ipaddress.ip_network(tpl_args).hosts() + self.assertIsNotNone(next(hosts)) self.assertEqual(addrs, list(ipaddress.ip_network(str_args).hosts())) self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), @@ -1529,6 +1539,12 @@ def testHosts(self): addrs = [ipaddress.IPv6Address('2001:658:22a:cafe::1'), ] str_args = '2001:658:22a:cafe::1/128' tpl_args = ('2001:658:22a:cafe::1', 128) + self.assertIsInstance(ipaddress.ip_network(str_args).hosts(), Iterator) + self.assertIsInstance(ipaddress.ip_network(tpl_args).hosts(), Iterator) + hosts = ipaddress.ip_network(str_args).hosts() + self.assertIsNotNone(next(hosts)) + hosts = ipaddress.ip_network(tpl_args).hosts() + self.assertIsNotNone(next(hosts)) self.assertEqual(addrs, list(ipaddress.ip_network(str_args).hosts())) self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), From 5e6bf4f593450c6dcf2cb23a187c93eb8d768397 Mon Sep 17 00:00:00 2001 From: Bonu Krishna Chaitanya Date: Sat, 15 Nov 2025 19:31:50 +0530 Subject: [PATCH 07/10] news entry changes --- .../Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst b/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst index 0bedc0522e85d4..9b79e5885bebdf 100644 --- a/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst +++ b/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst @@ -1,2 +1,2 @@ -In :mod:`ipaddress`, ensure that the methods ``IPv6Network.hosts()`` and -``IPv4Network.hosts()`` always returns an iterator. +:mod:`ipaddress`: ensure that the methods ``IPv4Network.hosts()`` and +``IPv6Network.hosts()`` always return an iterator. From 2bc46e7a07dd175704d5dbf7ecfd42c34023c183 Mon Sep 17 00:00:00 2001 From: Bonu Krishna Chaitanya Date: Sun, 16 Nov 2025 07:51:00 +0530 Subject: [PATCH 08/10] more tests --- Lib/test/test_ipaddress.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index b424055ebb31b4..abdb045ffd9051 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -12,8 +12,8 @@ import pickle import ipaddress import weakref -from test.support import LARGEST, SMALLEST from collections.abc import Iterator +from test.support import LARGEST, SMALLEST class BaseTestCase(unittest.TestCase): @@ -1491,6 +1491,9 @@ def testHosts(self): self.assertEqual(ipaddress.IPv6Address('2001:658:22a:cafe::ff'), hosts[-1]) ipv6_scoped_network = ipaddress.IPv6Network('2001:658:22a:cafe::%scope/120') + hosts = ipv6_scoped_network.hosts() + self.assertIsInstance(hosts, Iterator) + self.assertIsNotNone(next(hosts)) hosts = list(ipv6_scoped_network.hosts()) self.assertEqual(255, len(hosts)) self.assertEqual(ipaddress.IPv6Address('2001:658:22a:cafe::1'), hosts[0]) @@ -1501,6 +1504,12 @@ def testHosts(self): ipaddress.IPv4Address('2.0.0.1')] str_args = '2.0.0.0/31' tpl_args = ('2.0.0.0', 31) + self.assertIsInstance(ipaddress.ip_network(str_args).hosts(), Iterator) + self.assertIsInstance(ipaddress.ip_network(tpl_args).hosts(), Iterator) + hosts = ipaddress.ip_network(str_args).hosts() + self.assertIsNotNone(next(hosts)) + hosts = ipaddress.ip_network(tpl_args).hosts() + self.assertIsNotNone(next(hosts)) self.assertEqual(addrs, list(ipaddress.ip_network(str_args).hosts())) self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), From 3add543484b6bb8af5cbc74d390c701cc54ddad0 Mon Sep 17 00:00:00 2001 From: Bonu Krishna Chaitanya Date: Sun, 16 Nov 2025 07:58:37 +0530 Subject: [PATCH 09/10] news entry fix --- .../Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst b/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst index 9b79e5885bebdf..328bfe067ad96b 100644 --- a/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst +++ b/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst @@ -1,2 +1,4 @@ -:mod:`ipaddress`: ensure that the methods ``IPv4Network.hosts()`` and -``IPv6Network.hosts()`` always return an iterator. +:mod:`ipaddress`: ensure that the methods +:meth:`IPv4Network.hosts() ` and +:meth:`IPv6Network.hosts() ` always return an +iterator. From ccdf95161376de75668d83c1301bfdf8566aa586 Mon Sep 17 00:00:00 2001 From: Bonu Krishna Chaitanya Date: Mon, 17 Nov 2025 21:58:08 +0530 Subject: [PATCH 10/10] tests --- Lib/test/test_ipaddress.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index abdb045ffd9051..3f017b97dc28a3 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -1475,7 +1475,7 @@ def testGetSupernet4(self): def testHosts(self): hosts = self.ipv4_network.hosts() self.assertIsInstance(hosts, Iterator) - self.assertIsNotNone(next(hosts)) + self.assertEqual(ipaddress.IPv4Address('1.2.3.1'), next(hosts)) hosts = list(self.ipv4_network.hosts()) self.assertEqual(254, len(hosts)) self.assertEqual(ipaddress.IPv4Address('1.2.3.1'), hosts[0]) @@ -1484,7 +1484,7 @@ def testHosts(self): ipv6_network = ipaddress.IPv6Network('2001:658:22a:cafe::/120') hosts = ipv6_network.hosts() self.assertIsInstance(hosts, Iterator) - self.assertIsNotNone(next(hosts)) + self.assertEqual(ipaddress.IPv6Address('2001:658:22a:cafe::1'), next(hosts)) hosts = list(ipv6_network.hosts()) self.assertEqual(255, len(hosts)) self.assertEqual(ipaddress.IPv6Address('2001:658:22a:cafe::1'), hosts[0]) @@ -1493,7 +1493,7 @@ def testHosts(self): ipv6_scoped_network = ipaddress.IPv6Network('2001:658:22a:cafe::%scope/120') hosts = ipv6_scoped_network.hosts() self.assertIsInstance(hosts, Iterator) - self.assertIsNotNone(next(hosts)) + self.assertEqual((ipaddress.IPv6Address('2001:658:22a:cafe::1')), next(hosts)) hosts = list(ipv6_scoped_network.hosts()) self.assertEqual(255, len(hosts)) self.assertEqual(ipaddress.IPv6Address('2001:658:22a:cafe::1'), hosts[0]) @@ -1504,12 +1504,12 @@ def testHosts(self): ipaddress.IPv4Address('2.0.0.1')] str_args = '2.0.0.0/31' tpl_args = ('2.0.0.0', 31) - self.assertIsInstance(ipaddress.ip_network(str_args).hosts(), Iterator) - self.assertIsInstance(ipaddress.ip_network(tpl_args).hosts(), Iterator) hosts = ipaddress.ip_network(str_args).hosts() - self.assertIsNotNone(next(hosts)) + self.assertIsInstance(hosts, Iterator) + self.assertEqual(next(hosts), addrs[0]) hosts = ipaddress.ip_network(tpl_args).hosts() - self.assertIsNotNone(next(hosts)) + self.assertIsInstance(hosts, Iterator) + self.assertEqual(next(hosts), addrs[0]) self.assertEqual(addrs, list(ipaddress.ip_network(str_args).hosts())) self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), @@ -1519,12 +1519,12 @@ def testHosts(self): addrs = [ipaddress.IPv4Address('1.2.3.4')] str_args = '1.2.3.4/32' tpl_args = ('1.2.3.4', 32) - self.assertIsInstance(ipaddress.ip_network(str_args).hosts(), Iterator) - self.assertIsInstance(ipaddress.ip_network(tpl_args).hosts(), Iterator) hosts = ipaddress.ip_network(str_args).hosts() - self.assertIsNotNone(next(hosts)) + self.assertIsInstance(hosts, Iterator) + self.assertEqual(next(hosts), addrs[0]) hosts = ipaddress.ip_network(tpl_args).hosts() - self.assertIsNotNone(next(hosts)) + self.assertIsInstance(hosts, Iterator) + self.assertEqual(next(hosts), addrs[0]) self.assertEqual(addrs, list(ipaddress.ip_network(str_args).hosts())) self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), @@ -1534,12 +1534,12 @@ def testHosts(self): ipaddress.IPv6Address('2001:658:22a:cafe::1')] str_args = '2001:658:22a:cafe::/127' tpl_args = ('2001:658:22a:cafe::', 127) - self.assertIsInstance(ipaddress.ip_network(str_args).hosts(), Iterator) - self.assertIsInstance(ipaddress.ip_network(tpl_args).hosts(), Iterator) hosts = ipaddress.ip_network(str_args).hosts() - self.assertIsNotNone(next(hosts)) + self.assertIsInstance(hosts, Iterator) + self.assertEqual(next(hosts), addrs[0]) hosts = ipaddress.ip_network(tpl_args).hosts() - self.assertIsNotNone(next(hosts)) + self.assertIsInstance(hosts, Iterator) + self.assertEqual(next(hosts), addrs[0]) self.assertEqual(addrs, list(ipaddress.ip_network(str_args).hosts())) self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), @@ -1548,12 +1548,12 @@ def testHosts(self): addrs = [ipaddress.IPv6Address('2001:658:22a:cafe::1'), ] str_args = '2001:658:22a:cafe::1/128' tpl_args = ('2001:658:22a:cafe::1', 128) - self.assertIsInstance(ipaddress.ip_network(str_args).hosts(), Iterator) - self.assertIsInstance(ipaddress.ip_network(tpl_args).hosts(), Iterator) hosts = ipaddress.ip_network(str_args).hosts() - self.assertIsNotNone(next(hosts)) + self.assertIsInstance(hosts, Iterator) + self.assertEqual(next(hosts), addrs[0]) hosts = ipaddress.ip_network(tpl_args).hosts() - self.assertIsNotNone(next(hosts)) + self.assertIsInstance(hosts, Iterator) + self.assertEqual(next(hosts), addrs[0]) self.assertEqual(addrs, list(ipaddress.ip_network(str_args).hosts())) self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()),