[Python-Dev] PEP 3144 review.

Cameron Simpson cs at zip.com.au
Thu Sep 17 00:27:12 CEST 2009

On 15Sep2009 13:16, Scott Dial <scott+python-dev at scottdial.com> wrote:
| It just happened that I needed a tool today to calculate the gateway IP
| for an interface, and I took it as an opportunity to try out this ipaddr
| module. I'll attempt to relate my experience below...
| I have to concur with the opinions above. I was very confused by the
| following error:
| >>> addr = ipaddr.IPAddress("")
| ...
| ipaddr.IPAddressIPValidationError: '' is not
| a valid address (hint, it's probably a network)

It sure looks like a network to me, too.

| Because, it *is* a address of a host on a network. I gave in and said:

No, it is an IP address plus a network mask, and that notation is
generally used to describe a network (base IP of network plus the mask
to indicate its range).

| >>> net = ipaddr.IPNetwork("")
| But then, I was dumbfounded as to how I could get the gateway IP from
| this IPNetwork object. It took me a while to figure out that you can
| iterate over IPNetwork instances:
| >>> gateway = net[1]

Shrug. It is a common convention for a network's _default_ gateway to be the
network's base address + 1. But certainly not necessary. If that convention
is also your convention, then good.

| I was then confused, because:
| >>> print(type(gateway))
| <class 'ipaddr.IPv4Address'>
| Which sorta blew my mind.. I fully expected to receive an IPNetwork back
| from that operation.

I have no idea why you would expect that. A gateway is just the IP
_address_ of a host that will route packets to other networks. It is
inherently an address, and not a network.

Remember that a network (well, a host on a network) may have multiple
gateways; usually a single "default" gateway, and potentially others for
special routes to particular other networks. There's no need to have
just one gateway address.

Perhaps you are thinking of routing table entries (such as recited by
"netstat -r" on a UNIX box). They normally consist of a network
specification (base-addr/network-mask) and a gateway _address_.

| It is unclear to me why the network information
| gets chucked by that operation. I foresee having to work around that in
| real applications by doing something obnoxious like:
| >>> actual_gateway = ipaddr.IPNetwork("%s/%s" % (gateway, addr.netmask))
| But since I only actually needed the IP address for the gateway, it
| fulfilled my needs.

And that is a clue. You only need the gateway IP address in your needs
because a gateway _is_ an IP address.

It is quite possible you are thinking the word "gateway", but actually
thinking about a "route".

| In the end, I found the names IPNetwork/IPAddress and their
| instantiations confusing.

I really believe that you are confused in this instance, not the module.

| ISTM that IPNetwork is overloaded and plays
| two roles of being an IPNetwork and being an IPAddressWithNetwork. And
| finally, it's unclear to me why iterating over a IPNetwork would not
| produce a sequence of IPNetwork(/IPAddressWithNetwork) objects.
| ISTM that if I started with an IPNetwork object, the API should always
| return IPNetwork objects.

Not for methods that produce addresses!

| If I want just an IPAddress object, then I can
| always fetch the "ip" attribute to get that. Perhaps there is some
| compelling conceptual argument as to why this is not correct, but it
| seems like the API destroys information needlessly.

I really think you have the wrong mental image of what these terms mean.

Nothing in your examples seems surprising, confusing or wrong to me.

Cameron Simpson <cs at zip.com.au> DoD#743

More information about the Python-Dev mailing list