diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2014-05-12 18:36:46 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2014-05-12 18:36:46 (GMT) |
commit | 5fb195f854e6fe016015c98dfd379c1102950c04 (patch) | |
tree | 34fb65e46690ef8542381fdb5315bd6ad93403ee /Lib/ipaddress.py | |
parent | 3b5162d05d24a2f4cd6b2b9f5b503982cf433cd6 (diff) | |
download | cpython-5fb195f854e6fe016015c98dfd379c1102950c04.zip cpython-5fb195f854e6fe016015c98dfd379c1102950c04.tar.gz cpython-5fb195f854e6fe016015c98dfd379c1102950c04.tar.bz2 |
Issue #16531: ipaddress.IPv4Network and ipaddress.IPv6Network now accept an (address, netmask) tuple argument, so as to easily construct network objects from existing addresses.
Diffstat (limited to 'Lib/ipaddress.py')
-rw-r--r-- | Lib/ipaddress.py | 95 |
1 files changed, 74 insertions, 21 deletions
diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 1e451f8..216ddf1 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -991,15 +991,15 @@ class _BaseNetwork(_IPAddressBase): raise ValueError('cannot set prefixlen_diff and new_prefix') prefixlen_diff = self._prefixlen - new_prefix - if self.prefixlen - prefixlen_diff < 0: + new_prefixlen = self.prefixlen - prefixlen_diff + if new_prefixlen < 0: raise ValueError( 'current prefixlen is %d, cannot have a prefixlen_diff of %d' % (self.prefixlen, prefixlen_diff)) - # TODO (pmoody): optimize this. - t = self.__class__('%s/%d' % (self.network_address, - self.prefixlen - prefixlen_diff), - strict=False) - return t.__class__('%s/%d' % (t.network_address, t.prefixlen)) + return self.__class__(( + int(self.network_address) & (int(self.netmask) << prefixlen_diff), + new_prefixlen + )) @property def is_multicast(self): @@ -1389,6 +1389,18 @@ class IPv4Interface(IPv4Address): self._prefixlen = self._max_prefixlen return + if isinstance(address, tuple): + IPv4Address.__init__(self, address[0]) + if len(address) > 1: + self._prefixlen = int(address[1]) + else: + self._prefixlen = self._max_prefixlen + + self.network = IPv4Network(address, strict=False) + self.netmask = self.network.netmask + self.hostmask = self.network.hostmask + return + addr = _split_optional_netmask(address) IPv4Address.__init__(self, addr[0]) @@ -1504,22 +1516,42 @@ class IPv4Network(_BaseV4, _BaseNetwork): _BaseV4.__init__(self, address) _BaseNetwork.__init__(self, address) - # Constructing from a packed address - if isinstance(address, bytes): + # Constructing from a packed address or integer + if isinstance(address, (int, bytes)): self.network_address = IPv4Address(address) self._prefixlen = self._max_prefixlen self.netmask = IPv4Address(self._ALL_ONES) #fixme: address/network test here return - # Efficient constructor from integer. - if isinstance(address, int): - self.network_address = IPv4Address(address) - self._prefixlen = self._max_prefixlen - self.netmask = IPv4Address(self._ALL_ONES) - #fixme: address/network test here. + if isinstance(address, tuple): + if len(address) > 1: + # If address[1] is a string, treat it like a netmask. + if isinstance(address[1], str): + self.netmask = IPv4Address(address[1]) + self._prefixlen = self._prefix_from_ip_int( + int(self.netmask)) + # address[1] should be an int. + else: + self._prefixlen = int(address[1]) + self.netmask = IPv4Address(self._ip_int_from_prefix( + self._prefixlen)) + # We weren't given an address[1]. + else: + self._prefixlen = self._max_prefixlen + self.netmask = IPv4Address(self._ip_int_from_prefix( + self._prefixlen)) + self.network_address = IPv4Address(address[0]) + packed = int(self.network_address) + if packed & int(self.netmask) != packed: + if strict: + raise ValueError('%s has host bits set' % self) + else: + self.network_address = IPv4Address(packed & + int(self.netmask)) return + # Assume input argument to be string or any object representation # which converts into a formatted IP prefix string. addr = _split_optional_netmask(address) @@ -2030,6 +2062,16 @@ class IPv6Interface(IPv6Address): self.network = IPv6Network(self._ip) self._prefixlen = self._max_prefixlen return + if isinstance(address, tuple): + IPv6Address.__init__(self, address[0]) + if len(address) > 1: + self._prefixlen = int(address[1]) + else: + self._prefixlen = self._max_prefixlen + self.network = IPv6Network(address, strict=False) + self.netmask = self.network.netmask + self.hostmask = self.network.hostmask + return addr = _split_optional_netmask(address) IPv6Address.__init__(self, addr[0]) @@ -2147,18 +2189,29 @@ class IPv6Network(_BaseV6, _BaseNetwork): _BaseV6.__init__(self, address) _BaseNetwork.__init__(self, address) - # Efficient constructor from integer. - if isinstance(address, int): + # Efficient constructor from integer or packed address + if isinstance(address, (bytes, int)): self.network_address = IPv6Address(address) self._prefixlen = self._max_prefixlen self.netmask = IPv6Address(self._ALL_ONES) return - # Constructing from a packed address - if isinstance(address, bytes): - self.network_address = IPv6Address(address) - self._prefixlen = self._max_prefixlen - self.netmask = IPv6Address(self._ALL_ONES) + if isinstance(address, tuple): + self.network_address = IPv6Address(address[0]) + if len(address) > 1: + self._prefixlen = int(address[1]) + else: + self._prefixlen = self._max_prefixlen + self.netmask = IPv6Address(self._ip_int_from_prefix( + self._prefixlen)) + self.network_address = IPv6Address(address[0]) + packed = int(self.network_address) + if packed & int(self.netmask) != packed: + if strict: + raise ValueError('%s has host bits set' % self) + else: + self.network_address = IPv6Address(packed & + int(self.netmask)) return # Assume input argument to be string or any object representation |