summaryrefslogtreecommitdiffstats
path: root/Lib/ipaddress.py
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2014-05-12 18:36:46 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2014-05-12 18:36:46 (GMT)
commit5fb195f854e6fe016015c98dfd379c1102950c04 (patch)
tree34fb65e46690ef8542381fdb5315bd6ad93403ee /Lib/ipaddress.py
parent3b5162d05d24a2f4cd6b2b9f5b503982cf433cd6 (diff)
downloadcpython-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.py95
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