Add `next_network` method that returns the next closest network of prefix size *next_prefix*. to Lib.ipaddress
---------
Co-authored-by: Faisal Mahmood <killerklient@hotmail.co.uk>
Co-authored-by: Senthil Kumaran <senthil@python.org>
.. deprecated:: 3.7
It uses the same ordering and comparison algorithm as "<", "==", and ">"
+ .. method:: next_network(next_prefix=None)
+
+ Finds the next closest network of prefix size *next_prefix*. If
+ *next_prefix=None*, then the current network prefix will be used.
+ Returns a single network object.
+
+ Raises :exc:`ValueError` if *next_prefix* is out of range or no further
+ network of the requested size exists.
+
+ >>> IPv4Network('192.0.2.0/24').next_network()
+ IPv4Network('192.0.3.0/24')
+ >>> IPv4Network('192.0.2.0/24').next_network(next_prefix=25)
+ IPv4Network('192.0.3.0/25')
+ >>> IPv4Network('192.0.2.0/24').next_network(next_prefix=23)
+ IPv4Network('192.0.4.0/23')
+ >>> IPv4Network('192.0.80.0/22').next_network(next_prefix=18)
+ IPv4Network('192.0.128.0/18')
+ >>> IPv4Network('192.0.80.0/22').next_network(next_prefix=50)
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ raise ValueError(
+ ValueError: next prefix must be between 1 and 32
+ >>> IPv4Network('255.255.255.0/24').next_network()
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ raise ValueError(
+ ValueError: out of address space, cannot make another /24 network
+
+ .. versionadded:: 3.16
.. class:: IPv6Network(address, strict=True)
.. method:: supernet(prefixlen_diff=1, new_prefix=None)
.. method:: subnet_of(other)
.. method:: supernet_of(other)
+ .. method:: next_network(next_prefix=None)
.. method:: compare_networks(other)
Refer to the corresponding attribute documentation in
(Contributed by Przemysław Buczkowski and Serhiy Storchaka in :gh:`89869`.)
+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.
+
+
logging
-------
return (self.network_address.is_loopback and
self.broadcast_address.is_loopback)
+ def next_network(self, next_prefix=None):
+ """Get the next closest network with a specific prefix.
+
+ Args:
+ next_prefix: The desired next prefix length, if not specified the
+ same self.prefixlen will be used
+
+ Returns:
+ An IPv(4|6) Network object of the next closest network.
+
+ """
+ if next_prefix is None:
+ next_prefix = self.prefixlen
+ new_netmask = self.netmask
+ else:
+ if next_prefix < 1 or next_prefix > self.max_prefixlen:
+ raise ValueError(
+ f"next prefix must be between 1 and {self.max_prefixlen}"
+ )
+ new_netmask, _ = self._make_netmask(next_prefix)
+
+ bit_shift = (
+ self.max_prefixlen - next_prefix
+ if next_prefix <= self.prefixlen
+ else self.max_prefixlen - self.prefixlen
+ )
+
+ next_ip = (
+ ((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:
+ raise ValueError(
+ f"out of address space, cannot make another /{next_prefix} "
+ "network"
+ ) from None
+
class _BaseConstants:
self.assertEqual(list(ipaddress.ip_network(str_args).hosts()),
list(ipaddress.ip_network(tpl_args).hosts()))
+ def testNextNetwork(self):
+ ipv4 = ipaddress.IPv4Network('1.2.3.0/24')
+ self.assertEqual(
+ ipv4.next_network(),
+ ipaddress.IPv4Network('1.2.4.0/24'),
+ )
+ self.assertEqual(
+ ipv4.next_network(next_prefix=16),
+ ipaddress.IPv4Network('1.3.0.0/16'),
+ )
+ self.assertEqual(
+ ipv4.next_network(next_prefix=25),
+ ipaddress.IPv4Network('1.2.4.0/25'),
+ )
+
+ ipv6 = ipaddress.IPv6Network('2001:dbb8:aaaa:aaaa::/64')
+ self.assertEqual(
+ ipv6.next_network(),
+ ipaddress.IPv6Network('2001:dbb8:aaaa:aaab::/64'),
+ )
+ self.assertEqual(
+ ipv6.next_network(next_prefix=48),
+ ipaddress.IPv6Network('2001:dbb8:aaab::/48'),
+ )
+ self.assertEqual(
+ ipv6.next_network(next_prefix=88),
+ ipaddress.IPv6Network('2001:dbb8:aaaa:aaab::/88'),
+ )
+
+ def testNextNetworkWithBadPrefix(self):
+ self.assertRaises(ValueError, self.ipv4_network.next_network, 0)
+ self.assertRaises(ValueError, self.ipv4_network.next_network, 35)
+ self.assertRaises(ValueError, self.ipv6_network.next_network, 0)
+ self.assertRaises(ValueError, self.ipv6_network.next_network, 150)
+
+ def testNextNetworkOutOfAddressSpace(self):
+ ipv4 = ipaddress.IPv4Network('255.255.255.0/24')
+ self.assertRaises(ValueError, ipv4.next_network)
+ ipv6 = ipaddress.IPv6Network('ffff:ffff:ffff:ffff:ffff:ffff:ffff:0/112')
+ self.assertRaises(ValueError, ipv6.next_network)
+
def testFancySubnetting(self):
self.assertEqual(sorted(self.ipv4_network.subnets(prefixlen_diff=3)),
sorted(self.ipv4_network.subnets(new_prefix=27)))
--- /dev/null
+Add :meth:`~ipaddress.IPv4Network.next_network` and
+:meth:`~ipaddress.IPv6Network.next_network`. Patch by Faisal Mahmood.