Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Doc/whatsnew/3.16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,9 @@ io
ipaddress
---------

* Add :meth:`~ipaddress.IPv4Network.next_network` and
:meth:`~ipaddress.IPv6Network.next_network` methods to find the next nearest
network with a specific prefix size.
* Add :meth:`IPv4Network.next_network() <ipaddress.IPv4Network.next_network>`
and :meth:`IPv6Network.next_network() <ipaddress.IPv6Network.next_network>`
methods to find the next nearest network with a specific prefix size.
(Contributed by Faisal Mahmood in :gh:`87027`.)


Expand Down
16 changes: 9 additions & 7 deletions Lib/ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -1124,11 +1124,15 @@ def next_network(self, next_prefix=None):

Args:
next_prefix: The desired next prefix length, if not specified the
same self.prefixlen will be used
same self.prefixlen will be used.

Returns:
An IPv(4|6) Network object of the next closest network.

Raises:
ValueError: If next_prefix is outside the range of valid prefix
lengths, or if no further network of that size exists.

"""
if next_prefix is None:
next_prefix = self.prefixlen
Expand All @@ -1150,15 +1154,13 @@ def next_network(self, next_prefix=None):
((new_netmask._ip & self.network_address._ip) >> bit_shift) + 1
) << bit_shift

try:
return self.__class__(
f"{self._string_from_ip_int(next_ip)}/{next_prefix}"
)
except OverflowError:
if next_ip > self._ALL_ONES:
raise ValueError(
f"out of address space, cannot make another /{next_prefix} "
"network"
) from None
)

return self.__class__((next_ip, next_prefix))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While technically this style can be used self.__class__((next_ip, next_prefix)) m because IPv4Network and IPv6Network do the _split_addr_prefix, we do not advertise or mention about this the value of the address argument. This styled tripped me a bit.

I would prefer the previous style.

return self.__class__(
                f"{self._string_from_ip_int(next_ip)}/{next_prefix}"
            )

Because of what we say address can be in the doc strings of the class.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize that public docs document that.
https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Network
https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv6Network

The change might simply be a follow up doc string patch on here.

cpython/Lib/ipaddress.py

Lines 2301 to 2319 in a6d25db

address: A string or integer representing the IPv6 network or the
IP and prefix/netmask.
'2001:db8::/128'
'2001:db8:0000:0000:0000:0000:0000:0000/128'
'2001:db8::'
are all functionally the same in IPv6. That is to say,
failing to provide a subnetmask will create an object with
a mask of /128.
Additionally, an integer can be passed, so
IPv6Network('2001:db8::') ==
IPv6Network(42540766411282592856903984951653826560)
or, more generally
IPv6Network(int(IPv6Network('2001:db8::'))) ==
IPv6Network('2001:db8::')
strict: A boolean. If true, ensure that we have been passed
A true network address, eg, 2001:db8::1000/124 and not an
IP address on a network, eg, 2001:db8::1/124.



class _BaseConstants:
Expand Down
10 changes: 8 additions & 2 deletions Lib/test/test_ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -1596,9 +1596,15 @@ def testNextNetworkWithBadPrefix(self):

def testNextNetworkOutOfAddressSpace(self):
ipv4 = ipaddress.IPv4Network('255.255.255.0/24')
self.assertRaises(ValueError, ipv4.next_network)
self.assertRaisesRegex(
ValueError,
'out of address space, cannot make another /24 network',
ipv4.next_network)
ipv6 = ipaddress.IPv6Network('ffff:ffff:ffff:ffff:ffff:ffff:ffff:0/112')
self.assertRaises(ValueError, ipv6.next_network)
self.assertRaisesRegex(
ValueError,
'out of address space, cannot make another /112 network',
ipv6.next_network)

def testFancySubnetting(self):
self.assertEqual(sorted(self.ipv4_network.subnets(prefixlen_diff=3)),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
Add :meth:`~ipaddress.IPv4Network.next_network` and
:meth:`~ipaddress.IPv6Network.next_network`. Patch by Faisal Mahmood.
Add :meth:`IPv4Network.next_network() <ipaddress.IPv4Network.next_network>`
and :meth:`IPv6Network.next_network() <ipaddress.IPv6Network.next_network>`.
Patch by Faisal Mahmood.
Loading