[Python-Dev] PEP 3144 review.

Stephen J. Turnbull stephen at xemacs.org
Wed Sep 16 07:30:03 CEST 2009


I haven't looked closedly at the reference implementation, and my
experience is small.  So take this as "POLA to the naive new user of
the API" discussion.

Scott Dial writes:

 > This example here solidifies my support of RDM's suggestion of there
 > being 3 types:
 > 
 >     IPv4Address
 >     IPv4AddressWithNetwork (or as he called it: IPv4AddressWithMask)
 >     IPv4Network

IPv4AddressWithMask seems silly to me, implementation-wise.  IP
networks are conceptually globally unique (and even for unroutable
networks they're locally unique), and it seems to me that I want that
to be true internally (for example, I once implemented an IP network
type that maintains a hostname table).  If you need *the* network,
you'll have to look it up in a mask_to_network table (at least
internally).

Rather, don't you want to just give IPv4Address an attribute
'network'?  This could then be filled in by the indexing method on
IPv4Network.

Then deriving a mask from a network is trivial (networks need to know
their masks anyway), like so:

    IPv4Address('1.1.1.1').network.mask

giving you the mask if .network is known, else an attribute error if
.network is None.  But deriving *the* corresponding network from a
mask will require keeping a table of networks around.

 > that it is apparently the only way to input a host with a mask is the
 > second clue.

I don't see why you would want to do that.  Wouldn't you rather

    IPv4Address('1.1.1.1').network_from_mask('255.255.0.0')

and

    IPv4Address('1.1.1.1').set_network_from_mask('255.255.0.0')


 > If I have an IP (10.2.3.4) and I know the netmask (say, 255.255.0.0),
 > then how do I get the network that it is on? As it stands, the only way
 > I see to do this is to do:
 > 
 > >>> net = ipaddr.IPv4Network("10.2.3.4/255.255.0.0")
 > 
 > Which is strange, because I didn't input a *network*, I inputted an
 > *address* on a network.

No, you inputted a pair of dotted quads.  Dotted quads do triple duty
representing host addresses, network addresses, and network masks.
Since construction is a conversion anyway, I don't have any problem
with constructing a network from that pair so that your test:

 > >>> net[0] == net.ip

returns true.  Ie, the implementation can do

    class IPv4Network(...):
        def __init__(self, dotted_quad_pair_string):
            ip, mask = pair_string_to_int_pair(dotted_quad_pair_string)
            self.mask = mask
            self.ip = ip & mask

 > IPv4Network objects should *only* have a net.network.

That's a naming issue, though, isn't it?  I don't see a use for
net.ip != net.network, so you wouldn't have both of them.  If you *do*
have both for some reason, your test

    net[0] == net.ip

seems to have the semantics "How was I constructed?" and I don't see
why you can assert that should be True.

 > Hopefully at this point, I have made the case that IPv4Network already
 > is playing double-duty as a IPv4Network and IPv4AddressWithNetwork.

At this point, no, you've only made the point that you would try to
use it that way.  Maybe that's natural for you (and you're obviously
more expert than I), but it's not for me.  I haven't experienced a
need for the operations you're trying to do, but if I needed them,
I'd be looking for APIs on IPv4Address and IPv4Network like those I
described above, not an IPv4AddressWithNetwork type (ie, I would
expect that IPv4Address is implemented as IPv4AddressWithNetwork).



More information about the Python-Dev mailing list