New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ipaddress.ip_network(...).hosts() returns nothing for an IPv4 /32 #72763
Comments
I would expect the following code to return ['10.9.8.8'] but it returns an empty list. yosemite-osx$ python3
Python 3.5.1 (default, Dec 26 2015, 18:08:53)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import ipaddress
>>> list(ipaddress.ip_network('10.9.8.7/32').hosts())
[] This seems to happen for every /32 address. I'm guessing the logic which wants to exclude the gateway and broadcast addresses from a block should treat a /32 as a special case. I tried to look for a previous bug submission but I could not find one. As such, it seems peculiar if this has not been reported before. Is this actually expected behavior by some rule I am overlooking? I tested on Linux 3.4 and OSX Yosemite Homebrew / Python 3.5.1. |
(Meh, silly typo, of course the expected output is ['10.9.8.7'], sorry about that!) |
hosts() won't return the network address itself and the network broadcast address. So for 10.9.8.7/32, it should return []. |
@xiang.zhang thanks for the quick reply. I find this behavior surprising. If I process a list of addresses, like ips = (
'10.9.8.7/32'
'10.11.12.8/28'
)
for test in ['10.9.8.7', '10.11.12.10']:
if test in [str(y) for x in ips for y in ipaddress.ip_network(x).hosts()]:
print('{0} found'.format(test))
else:
print('{0} not found'.format(test)) I would expect both addresses to print "found", but that's not how the current implementation works. I agree that the /28 should not include the gateway and broadcast addresses, but I would not expect the explicitly listed /32 address to completely disappear from the output. Are my expectations incorrect? For code like this, what should I use instead, if not hosts()? |
I am not sure. Actually there is a special case for mask 31, you can see bpo-27863. Its result includes both the network and broadcast address. Add Nick to see his opinion. FYI, ipaddress (ipaddr in Py2) always return empty for 32. But there is other library returning network address for 32, for example netaddr. |
Quick googling did not turn up anything like a credible authoritative reference for this, but in actual practice, I have seen /32 used to designate a single individual IP address in CIDR notation quite a lot. I can see roughly three options:
By the by, I don't see how the bug you linked to is relevant here, did you mistype the bug number? bpo-27863 is about _elementtree |
Sorry, it's bpo-27683. |
I think this is an area where ipaddress just inherited ipaddr's behaviour without challenging it. As Peter isn't currently particularly active, and I stepped back from ipaddress maintenance some time ago (since I don't work heavily enough with raw IP addresses to have the right design instincts to arbitrate edge cases like this), I'd suggest raising both this and bpo-27683 on python-dev, pointing out that we used to have the "/31" special case (treating it the same as "/30") and inadvertently lost it in some other refactoring, but have never special cased "/32". |
I fixed bpo-27683 since it looks more like an oversight and regression to me instead of a deliberate change. I'd like the behaviour to be consistent across versions. As for "/32", it needs discussion or some expert makes a choice. |
I came across this /32 issue today trying to iterate over the hosts in 127.0.0.1/32. I think it's fair to say that any /32 network has precisely one host, and that host should by returned by IPv4Network().hosts(). |
I've had a go at implementing this. I did not implement for IPv6 as this was not mentioned here, but it seems like it would make sense for it as well. I can add that in too if you like. |
Ok it was bugging me that they were different, so I also added the same logic for IPv6Networks. |
The patch for this has been merged - I guess this can be closed now? |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: