https://github.com/python/cpython/commit/060118ae918937d88760f384d0b0edf3f5251876
commit: 060118ae918937d88760f384d0b0edf3f5251876
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2025-11-17T17:56:55Z
summary:
[3.14] gh-141497: Make ipaddress.IP{v4,v6}Network.hosts() always returning an
iterator (GH-141547) (GH-141673)
(cherry picked from commit 6b1bdf6c7a6c87f12a247a125e25f8e721cc731e)
Co-authored-by: Krishna Chaitanya
<[email protected]>
files:
A Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst
M Lib/ipaddress.py
M Lib/test/test_ipaddress.py
diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py
index 8b60b9d5c9cd51..ca732e4f2e85a8 100644
--- a/Lib/ipaddress.py
+++ b/Lib/ipaddress.py
@@ -1545,7 +1545,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()
@@ -2336,7 +2336,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.
diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py
index db1c38243e2268..8af91e857d80ed 100644
--- a/Lib/test/test_ipaddress.py
+++ b/Lib/test/test_ipaddress.py
@@ -12,6 +12,7 @@
import pickle
import ipaddress
import weakref
+from collections.abc import Iterator
from test.support import LARGEST, SMALLEST
@@ -1472,18 +1473,27 @@ def testGetSupernet4(self):
self.ipv6_scoped_network.supernet(new_prefix=62))
def testHosts(self):
+ hosts = self.ipv4_network.hosts()
+ self.assertIsInstance(hosts, Iterator)
+ 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])
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)
+ 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])
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.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])
@@ -1494,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)
+ hosts = ipaddress.ip_network(str_args).hosts()
+ self.assertIsInstance(hosts, Iterator)
+ self.assertEqual(next(hosts), addrs[0])
+ hosts = ipaddress.ip_network(tpl_args).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()),
@@ -1503,6 +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)
+ hosts = ipaddress.ip_network(str_args).hosts()
+ self.assertIsInstance(hosts, Iterator)
+ self.assertEqual(next(hosts), addrs[0])
+ hosts = ipaddress.ip_network(tpl_args).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()),
@@ -1512,6 +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)
+ hosts = ipaddress.ip_network(str_args).hosts()
+ self.assertIsInstance(hosts, Iterator)
+ self.assertEqual(next(hosts), addrs[0])
+ hosts = ipaddress.ip_network(tpl_args).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()),
@@ -1520,6 +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)
+ hosts = ipaddress.ip_network(str_args).hosts()
+ self.assertIsInstance(hosts, Iterator)
+ self.assertEqual(next(hosts), addrs[0])
+ hosts = ipaddress.ip_network(tpl_args).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()),
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..328bfe067ad96b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-11-14-16-24-20.gh-issue-141497.L_CxDJ.rst
@@ -0,0 +1,4 @@
+:mod:`ipaddress`: ensure that the methods
+:meth:`IPv4Network.hosts() <ipaddress.IPv4Network.hosts>` and
+:meth:`IPv6Network.hosts() <ipaddress.IPv6Network.hosts>` always return an
+iterator.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]