msg271972 - (view) |
Author: (tklausmann) |
Date: 2016-08-04 13:07 |
Between Python 3.4 (3.4.5 I've tested with) and Python 3.5 (3.5.2), the behavior of ipaddress's subnet() method changed. This code: $ cat iat.py import ipaddress p = ipaddress.IPv4Network("172.0.0.4/30") subnets = p.subnets(new_prefix=31) n = next(subnets) print(list(n.hosts())) has two different outcomes on 3.4 vs. 3.5: $ python3.4 iat.py [IPv4Address('172.0.0.4'), IPv4Address('172.0.0.5')] $ python3.5 iat.py [] AIUI, the 3.4 behavior is the correct one (or the docs need to be fixed). |
|
|
msg271974 - (view) |
Author: R. David Murray (r.david.murray) *  |
Date: 2016-08-04 13:21 |
If someone wants to bisect to find out which changeset introduced the behavior change that would be helpful. |
|
|
msg271976 - (view) |
Author: Serhiy Storchaka (serhiy.storchaka) *  |
Date: 2016-08-04 13:43 |
The change was introduced in . |
|
|
msg271979 - (view) |
Author: (tklausmann) |
Date: 2016-08-04 14:22 |
I just bisected it and the specific commit is this one: https://hg.python.org/cpython/rev/2711677cf874 |
|
|
msg271981 - (view) |
Author: R. David Murray (r.david.murray) *  |
Date: 2016-08-04 14:47 |
Since this is a regression, I'm going to claim this has higher than normal priority, for whatever good that will do :) |
|
|
msg271982 - (view) |
Author: Anilyka Barry (abarry) *  |
Date: 2016-08-04 14:51 |
Here's a patch that fixes this bug, test included. I made this against the 3.5 branch, but should apply cleanly on default. |
|
|
msg271983 - (view) |
Author: Stephen Shirley (kormat) |
Date: 2016-08-04 14:53 |
The bug appears to be in the new form of the constructor. Here's a more minimal reproduction: In python3.5: >>> list(ipaddress.IPv4Network(("127.0.0.4", 31)).hosts()) [] In python3.4 >>> list(ipaddress.IPv4Network("127.0.0.4/31").hosts()) [IPv4Address('127.0.0.4'), IPv4Address('127.0.0.5')] |
|
|
msg272018 - (view) |
Author: Alyssa Coghlan (ncoghlan) *  |
Date: 2016-08-05 06:32 |
As Stephen notes, the underlying problem appears to be a behavioural difference between two theoretically equivalent ways of defining a network: >>> list(ipaddress.IPv4Network(('127.0.0.4', 31)).hosts()) [] >>> list(ipaddress.IPv4Network(('127.0.0.4/31')).hosts()) [IPv4Address('127.0.0.4'), IPv4Address('127.0.0.5')] Now, the first case is the documented behaviour: hosts() is *supposed to* exclude the network and broadcast address, and those are the only addresses in a /31. If you want to iterate over all the *addresses* in a network (including the network and broadcast addresses) then you need to iterate over the network object directly: >>> list(ipaddress.IPv4Network(('127.0.0.4', 31))) [IPv4Address('127.0.0.4'), IPv4Address('127.0.0.5')] >>> list(ipaddress.IPv4Network(('127.0.0.4/31'))) [IPv4Address('127.0.0.4'), IPv4Address('127.0.0.5')] However, as Emanuel found when writing his patch, there's currently an undocumented special case for /31 networks: the definition of "hosts" is *implicitly changed* for such instances to include the nominal network and broadcast address (by setting "self.hosts = self.__iter__"), presumably on the assumption that such networks represent a point-to-point link between two hosts, so the concepts of "network address" and "broadcast address" don't really apply. That special case seems pragmatically useful, so I think the right fix would be to: - document the special case that for /31 networks, hosts() includes the network and broadcast addresses (on the assumption the "network" is actually a point-to-point link between two hosts) - refactor IPv4Network.__init__ to first map the supplied input to a "candidate_address" and "candidate_netmask" and then use *common* validation logic to determine the actual network address and netmask (this will also address the "# fixme" comment for the int/bytes case) - check whether or not IPv6Network is affected by the same behavioural discrepancy |
|
|
msg272031 - (view) |
Author: Anilyka Barry (abarry) *  |
Date: 2016-08-05 14:10 |
Ack, special cases! I can look into making a patch, but I'm not really acquainted with ipaddress or the relevant protocols, so it might not be optimal. I'll give it a shot next week if nobody else does. |
|
|
msg273419 - (view) |
Author: Xiang Zhang (xiang.zhang) *  |
Date: 2016-08-23 07:32 |
.patch tries to fix this. It alters the doc and refactors the constructor, so there is no difference between different arguments As for IPv6Network, it has the same problem. |
|
|
msg274756 - (view) |
Author: Xiang Zhang (xiang.zhang) *  |
Date: 2016-09-07 04:30 |
ping :) |
|
|
msg279609 - (view) |
Author: Xiang Zhang (xiang.zhang) *  |
Date: 2016-10-28 15:35 |
Ping. ;-) |
|
|
msg279866 - (view) |
Author: (era) |
Date: 2016-11-01 09:55 |
#28577 requests a similar special case for /32 |
|
|
msg314175 - (view) |
Author: Xiang Zhang (xiang.zhang) *  |
Date: 2018-03-21 00:25 |
New changeset 10b134a07c898c2fbc5fd3582503680a54ed80a2 by Xiang Zhang in branch 'master': bpo-27683: Fix a regression for host() of ipaddress network objects (GH-6016) https://github.com/python/cpython/commit/10b134a07c898c2fbc5fd3582503680a54ed80a2 |
|
|
msg314178 - (view) |
Author: miss-islington (miss-islington) |
Date: 2018-03-21 01:22 |
New changeset 3326c9267f9df15fa77094b8a740be4eaa4b9374 by Miss Islington (bot) in branch '3.7': bpo-27683: Fix a regression for host() of ipaddress network objects (GH-6016) https://github.com/python/cpython/commit/3326c9267f9df15fa77094b8a740be4eaa4b9374 |
|
|
msg314181 - (view) |
Author: miss-islington (miss-islington) |
Date: 2018-03-21 01:49 |
New changeset ae2feb32e7eff328199ce7d527593b3c2aa1fcab by Miss Islington (bot) in branch '3.6': bpo-27683: Fix a regression for host() of ipaddress network objects (GH-6016) https://github.com/python/cpython/commit/ae2feb32e7eff328199ce7d527593b3c2aa1fcab |
|
|