On Aug 21, 2013, at 15:55, Jon Foster firstname.lastname@example.org wrote:
And that's because equality has been redefined:
IPv4Address('22.214.171.124') == IPv4Interface('126.96.36.199/24')
But why should you expect these to be equal? The interface is-a address, but isn't _that_ address.
Of course an interface isn't equal to _any_ address instance (that isn't also an interface instance), but so what? That's actually _typical_ of class hierarchies, not unusual. Imagine that we had Range with start and stop, and SteppedRange with start, stop, and step. Any SteppedRange with a step != 1 would be unequal to any (non-SteppedRange) Range, but it's still usable as a Range. This is exactly the same situation here.
In fact, your example shows that you can store addresses and interfaces together, and use them all as addresses, rather than the opposite--in other words, it fits the LSP perfectly.
All that being said, it does feel weird that an interface is an address. While it may satisfy the syntax of an address, it doesn't work behaviorally in most typical uses. For example, socket.connect((str(addr), port)) is the most obvious useful thing to do with an address, and it's not going to work if addr is an interface...
So, I think you may have found a real problem, even if your argument for why it's a problem isn't that compelling.
Meanwhile, PEP 3144 explains that "ipaddr makes extensive use of inheritance to avoid code duplication...", but that bit doesn't apply here, and I don't see any other justification for the inheritance here in the PEP, docs, or source. So I think we have to dig through the discussions (which may mean going back to the predecessor library's discussions) to see what the intended benefit is.