This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: ipaddress network subnets() method should return object with __getitem__
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.5
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: r.david.murray, vstinner, wt
Priority: normal Keywords:

Created on 2014-03-06 18:53 by wt, last changed 2022-04-11 14:57 by admin.

Messages (7)
msg212836 - (view) Author: Wren Turkal (wt) Date: 2014-03-06 18:53
It would be very useful to be able to not only iterate through subnets, but also index a subnet. For example, I would really like to be able to do the following:

>>> import ipaddress as ipa
>>> net = ipa.ip_network('10.0.0.0/8')
>>> print(net.subnets(prefixlen_diff=2)[2])
"10.128.0.0/10"

As it stands now, I have to write something like the following to get the same result:

>>> import ipaddress as ipa
>>> net = ipa.ip_network('10.0.0.0/8')
>>> subnets = net.subnets(prefixlen_diff=2)
>>> for _ in xrange(0, 3):
...     subnet = subnets.next()
...
>>> print(subnet)
"10.128.0.0/10"


The simplest way I can come up with to add this feature is by wrapping the current body of that method in a nested generator function, creating an instance of that generator, adding a appropriate __getitem__ method to that object, and returning that object instead of the bare generator. What do you all think of that?

Also, it'd be nice to see this added to the ipaddress module on pypi for python 2.x also. :)
msg212838 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-03-06 19:08
I think you are looking for list(net.subnets(prefixlen_diff=2))[2].  This is the standard Python way of going from an iterator to an indexable collection.
msg212844 - (view) Author: Wren Turkal (wt) Date: 2014-03-06 21:53
Won't that instantiate an object for each item in the list though? For example:

>>> list(net.subnets(prefixlen_diff=16))[499]

This take a long time. I was trying to think of a way to lazily instantiate.

For example, I don't want to create 65536 network objects (like above) if I am looking for the 500th /24 subnet of 10.0.0.0/8. The following executes much more quickly:

>>> ipa.ip_network((10 << 24) + (499 << 8))

That essentially what the __getattr__ method should do. Of course, it might also be nice to have a __len__ on that object.
msg212845 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-03-06 22:14
The interface you are suggesting isn't consistent with other stdlib APIs.  Perhaps it would be better to discuss this concept on pyhon-ideas...additional methods for computing the number of subnets for a given prefix, and a different one for constructing one of them, perhaps?  The use cases and appropriate API aren't clear, which is why I suggest taking it to python-ideas.
msg212847 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-03-06 22:18
Or maybe a subnet_range method that returns a range-like object.
msg212848 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-03-06 22:28
I reopen the issue because the list option may create an huge list. Try the IPv6 2000::/3 network :-)
msg212849 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2014-03-06 22:33
"It would be very useful to be able to not only iterate through subnets, but also index a subnet."

For your information, the IPy module supports that:

>>> tuple(IPy.IP('192.168.1.128/31'))
(IP('192.168.1.128'), IP('192.168.1.129'))
>>> IPy.IP('2000::/3')[2**120]
IP('2100::')
History
Date User Action Args
2022-04-11 14:57:59adminsetgithub: 65059
2014-03-06 22:33:01vstinnersetmessages: + msg212849
2014-03-06 22:28:12vstinnersetstatus: closed -> open

nosy: + vstinner
messages: + msg212848

resolution: rejected ->
2014-03-06 22:18:17r.david.murraysetmessages: + msg212847
2014-03-06 22:14:13r.david.murraysetmessages: + msg212845
2014-03-06 21:53:31wtsetmessages: + msg212844
2014-03-06 19:08:06r.david.murraysetstatus: open -> closed

nosy: + r.david.murray
messages: + msg212838

resolution: rejected
stage: resolved
2014-03-06 18:53:27wtcreate