From 515ff89cd3efc162708e332252f2df0e19c49cb1 Mon Sep 17 00:00:00 2001 From: Pete Wicken Date: Mon, 2 Mar 2020 23:47:07 +0000 Subject: [PATCH 1/6] Special case added to IPv4Network hosts for /32 networks --- Doc/library/ipaddress.rst | 5 ++++- Lib/ipaddress.py | 2 ++ Lib/test/test_ipaddress.py | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index 5938439941792d..2ba653d7626066 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -509,7 +509,8 @@ dictionaries. hosts are all the IP addresses that belong to the network, except the network address itself and the network broadcast address. For networks with a mask length of 31, the network address and network broadcast - address are also included in the result. + address are also included in the result. Networks with a mask of 32 + will return a list containing the single host address, >>> list(ip_network('192.0.2.0/29').hosts()) #doctest: +NORMALIZE_WHITESPACE [IPv4Address('192.0.2.1'), IPv4Address('192.0.2.2'), @@ -517,6 +518,8 @@ dictionaries. IPv4Address('192.0.2.5'), IPv4Address('192.0.2.6')] >>> list(ip_network('192.0.2.0/31').hosts()) [IPv4Address('192.0.2.0'), IPv4Address('192.0.2.1')] + >>> list(ip_network('192.0.2.1/32').hosts()) + [IPv4Address('192.0.2.1')] .. method:: overlaps(other) diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 9c47405ce8d8c6..7c863079a168cf 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1509,6 +1509,8 @@ 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)] @property @functools.lru_cache() diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index f4a4afba76a99d..27a3f8e33b7c92 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -1424,6 +1424,15 @@ def testHosts(self): self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), list(ipaddress.ip_network(tpl_args).hosts())) + # special case where the network is a /32 + addrs = [ipaddress.IPv4Address('1.2.3.4')] + str_args = '1.2.3.4/32' + tpl_args = ('1.2.3.4', 32) + 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()), + list(ipaddress.ip_network(tpl_args).hosts())) + addrs = [ipaddress.IPv6Address('2001:658:22a:cafe::'), ipaddress.IPv6Address('2001:658:22a:cafe::1')] str_args = '2001:658:22a:cafe::/127' From 0bbed0e1f5f7a25585e00402d8ef15affe97cba4 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2020 23:52:39 +0000 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2020-03-02-23-52-38.bpo-28577.EK91ae.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2020-03-02-23-52-38.bpo-28577.EK91ae.rst diff --git a/Misc/NEWS.d/next/Library/2020-03-02-23-52-38.bpo-28577.EK91ae.rst b/Misc/NEWS.d/next/Library/2020-03-02-23-52-38.bpo-28577.EK91ae.rst new file mode 100644 index 00000000000000..1952e631d5bc20 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-02-23-52-38.bpo-28577.EK91ae.rst @@ -0,0 +1 @@ +The hosts method on a /32 IPv4Network now returns a list containing the IPv4Address instead of an empty list. \ No newline at end of file From b7c888a6a55b9157c0c95f391040fccd08b39b26 Mon Sep 17 00:00:00 2001 From: Pete Wicken Date: Tue, 3 Mar 2020 08:59:11 +0000 Subject: [PATCH 3/6] Special case added to IPv6Network hosts for /128 networks Signed-off-by: Pete Wicken --- Doc/library/ipaddress.rst | 4 +++- Lib/ipaddress.py | 2 ++ Lib/test/test_ipaddress.py | 8 ++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index 2ba653d7626066..eb16186236e25d 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -510,7 +510,7 @@ dictionaries. network address itself and the network broadcast address. For networks with a mask length of 31, the network address and network broadcast address are also included in the result. Networks with a mask of 32 - will return a list containing the single host address, + will return a list containing the single host address. >>> list(ip_network('192.0.2.0/29').hosts()) #doctest: +NORMALIZE_WHITESPACE [IPv4Address('192.0.2.1'), IPv4Address('192.0.2.2'), @@ -681,6 +681,8 @@ dictionaries. hosts are all the IP addresses that belong to the network, except the Subnet-Router anycast address. For networks with a mask length of 127, the Subnet-Router anycast address is also included in the result. + Networks with a mask of 128 will return a list containing the + single host address. .. method:: overlaps(other) .. method:: address_exclude(network) diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 7c863079a168cf..bc9b7124fe2408 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -2214,6 +2214,8 @@ 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)] 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 27a3f8e33b7c92..bbb3fc89da6533 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -1441,10 +1441,10 @@ def testHosts(self): self.assertEqual(addrs, list(ipaddress.ip_network(tpl_args).hosts())) self.assertEqual(list(ipaddress.ip_network(str_args).hosts()), list(ipaddress.ip_network(tpl_args).hosts())) - addrs = [ipaddress.IPv6Address('2001:658:22a:cafe::'), - ipaddress.IPv6Address('2001:658:22a:cafe::1')] - str_args = '2001:658:22a:cafe::/127' - tpl_args = ('2001:658:22a:cafe::', 127) + + 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.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 1c28891c2ce8f45b7f02f91423092c5881d55cc4 Mon Sep 17 00:00:00 2001 From: Pete Wicken <2273100+JamoBox@users.noreply.github.com> Date: Tue, 3 Mar 2020 09:09:17 +0000 Subject: [PATCH 4/6] Updated News Added IPv6 update to news --- .../next/Library/2020-03-02-23-52-38.bpo-28577.EK91ae.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2020-03-02-23-52-38.bpo-28577.EK91ae.rst b/Misc/NEWS.d/next/Library/2020-03-02-23-52-38.bpo-28577.EK91ae.rst index 1952e631d5bc20..de4c064378c247 100644 --- a/Misc/NEWS.d/next/Library/2020-03-02-23-52-38.bpo-28577.EK91ae.rst +++ b/Misc/NEWS.d/next/Library/2020-03-02-23-52-38.bpo-28577.EK91ae.rst @@ -1 +1 @@ -The hosts method on a /32 IPv4Network now returns a list containing the IPv4Address instead of an empty list. \ No newline at end of file +The hosts method on 32-bit prefix length IPv4Networks and 128-bit prefix IPv6Networks now returns a list containing the single Address instead of an empty list. From 81e95099ec7b226664322100a86de14fef02b029 Mon Sep 17 00:00:00 2001 From: Pete Wicken Date: Tue, 3 Mar 2020 19:33:13 +0000 Subject: [PATCH 5/6] Fixed trailing whitespace --- Doc/library/ipaddress.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index eb16186236e25d..5f5e66412da477 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -681,7 +681,7 @@ dictionaries. hosts are all the IP addresses that belong to the network, except the Subnet-Router anycast address. For networks with a mask length of 127, the Subnet-Router anycast address is also included in the result. - Networks with a mask of 128 will return a list containing the + Networks with a mask of 128 will return a list containing the single host address. .. method:: overlaps(other) From 87cb535abde5cb665c866b3ac57667af5807eb02 Mon Sep 17 00:00:00 2001 From: Pete Wicken Date: Tue, 3 Mar 2020 19:34:24 +0000 Subject: [PATCH 6/6] updated ACKS --- Misc/ACKS | 1 + 1 file changed, 1 insertion(+) diff --git a/Misc/ACKS b/Misc/ACKS index 5ec93a43755afd..cc5694af008b32 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1823,6 +1823,7 @@ Jeff Wheeler Christopher White David White Mats Wichmann +Pete Wicken Marcel Widjaja Truida Wiedijk Felix Wiemann