Thanks Jakub, I wasn't aware of the netaddr library but just gave it a play and it does seem very similar and I think it's very useful and completely valid.
I think the subtle difference is also that my implementation allows you to specify the next prefix as well, so it won't just find the next prefix of the same size. This is a common use case when you are trying to find free address spaces, you will need to look for networks of different sizes depending on what you are doing.
Currently, you could say that you were given a network of 10.200.20.0/24 and asked to split this network into a bunch of /26 networks, you can do this easily using the subnets method: *>>> list(IPv4Network("10.200.20.0/24 http://10.200.20.0/24").subnets(prefixlen_diff=2))* *[IPv4Network('10.200.20.0/26' http://10.200.20.0/26'), IPv4Network('10.200.20.64/26' http://10.200.20.64/26'), IPv4Network('10.200.20.128/26' http://10.200.20.128/26'), IPv4Network('10.200.20.192/26' http://10.200.20.192/26')]*
That is very simple and effective, but not a very realistic example of how you would split networks up. Given how limited the IPv4 address space is, normally you may have to use that /24 block for multiple things, so can't just simply split it up into /26's, you may need to instead get two /30's, one /27 and one /25. Currently, I don't think there is any straightforward way to do this without a 'next_network' method that I have implemented.
Example, given a network of 10.200.20.0/24, to get two /30's out of it, one /27 and one /25, I would do the following with my method: *>>> first_network = IPv4Network("10.200.20.0/30 http://10.200.20.0/30")* *# first_network = IPv4Network("10.200.20.0/30 http://10.200.20.0/30")*
Then get the next one (note not specifying prefix just gives me another /30 - i.e. same prefix size): *>>> second_network = first_network.next_network()* *# second_network = IPv4Network("10.200.20.4/30 http://10.200.20.4/30")*
Then I would need to get the /27, so do this: *>>> third_network = second_network.next_network(new_prefixlen=27)* *# third_network = IPv4Network("10.200.20.32/27 http://10.200.20.32/27)*
Finally the /25: *>>> fourth_network = third_network.next_network(new_prefixlen=25)* *# fourth_network = IPv4Network("10.200.20.128/25 http://10.200.20.128/25)*
When you are dealing with the same prefix size for each new network, I think it's just a simple case of adding 1 to the broadcast address each time, but when you have different prefix sizes it's a bit more complicated.
On Sat, 20 Mar 2021 at 22:04, Jakub Stasiak firstname.lastname@example.org wrote:
On 20 Mar 2021, at 04:39, Guido van Rossum email@example.com wrote:
Honestly this is an example of a module that would have been better off
outside the stdlib.
On Fri, Mar 19, 2021 at 14:43 Senthil Kumaran firstname.lastname@example.org
On Mon, Feb 15, 2021 at 8:36 AM Faisal Mahmood email@example.com wrote:
I hope you are all well, I currently have an issue / merge request
that has become stale and as per the guidelines I am sending this e-mail to request someone to review it for me please.
Issue Number: 42861 (https://bugs.python.org/issue42861) Pull Request: 24180 (https://github.com/python/cpython/pull/24180)
Could you share some motivation references that could help explain why this next_network method will be helpful? Is this common enough to warrant a method in the stdlib IP-Address module? If there is prior-art in other external libraries or libraries of other languages, that will be helpful to know and review too.
I had looked at this a month ago when you pinged for review, but I could not immediately determine the benefit of having this method in stdlib, irrespective of implementation correctness or API Signature. I also lack extensive experience with ipv6.
I don’t know if this is gonna support Faisal’s cause (“It’s used in a third party library in the wild, that means stdlib could use it!”) or the exact opposite (“it’s provided by a third party library, so may as well use third party library and stdlib doesn’t necessarily need this”) but the quite popular netaddr library that I’m a maintainer of does have IPNetwork.next() and IPNetwork.previous() methods. The main difference is that in netaddr:
- next() and previous() can produce networks arbitrary number of steps
away, not just the first closest network forwards or backwards
- going from a network to its supernetwork or subnetwork is done through a
separate set of supernet() and subnet() methods
I can’t say how many library users actually consume this particular section of the API, of course, but I expect this API to be used and it seems rather useful.
 https://netaddr.readthedocs.io/en/latest/api.html#netaddr.IPNetwork.next  https://netaddr.readthedocs.io/en/latest/api.html#netaddr.IPNetwork.previous  https://netaddr.readthedocs.io/en/latest/api.html#netaddr.IPNetwork.subnet  https://netaddr.readthedocs.io/en/latest/api.html#netaddr.IPNetwork.supernet