summaryrefslogtreecommitdiff
path: root/Lib/ipaddress.py
diff options
context:
space:
mode:
authorInada Naoki <songofacandy@gmail.com>2019-04-16 08:32:28 +0900
committerGitHub <noreply@github.com>2019-04-16 08:32:28 +0900
commit6fa84bd12c4b83bee6a41b989363230d5c03b96c (patch)
tree846220dfd35742385323c4dc2742edc3b6ed7a29 /Lib/ipaddress.py
parent74125a60b7a477451ff2b8385bfbce3fdaee8dbc (diff)
downloadcpython-git-6fa84bd12c4b83bee6a41b989363230d5c03b96c.tar.gz
bpo-27860: ipaddress: fix Interface missed some attributes (GH-12836)
IPv4Interface and IPv6Interface did not has netmask and hostmask attributes when its argument is bytes or int. This commit extracts method for constructors of Network and Interface, and ensure Interface class always provides them.
Diffstat (limited to 'Lib/ipaddress.py')
-rw-r--r--Lib/ipaddress.py110
1 files changed, 40 insertions, 70 deletions
diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py
index 7a3f36f3bc..909a55de4f 100644
--- a/Lib/ipaddress.py
+++ b/Lib/ipaddress.py
@@ -532,6 +532,30 @@ class _IPAddressBase:
except ValueError:
cls._report_invalid_netmask(ip_str)
+ @classmethod
+ def _split_addr_prefix(cls, address):
+ """Helper function to parse address of Network/Interface.
+
+ Arg:
+ address: Argument of Network/Interface.
+
+ Returns:
+ (addr, prefix) tuple.
+ """
+ # a packed address or integer
+ if isinstance(address, (bytes, int)):
+ return address, cls._max_prefixlen
+
+ if not isinstance(address, tuple):
+ # Assume input argument to be string or any object representation
+ # which converts into a formatted IP prefix string.
+ address = _split_optional_netmask(address)
+
+ # Constructing from a tuple (addr, [mask])
+ if len(address) > 1:
+ return address
+ return address[0], cls._max_prefixlen
+
def __reduce__(self):
return self.__class__, (str(self),)
@@ -1305,32 +1329,16 @@ class IPv4Address(_BaseV4, _BaseAddress):
class IPv4Interface(IPv4Address):
def __init__(self, address):
- if isinstance(address, (bytes, int)):
- IPv4Address.__init__(self, address)
- self.network = IPv4Network(self._ip)
- 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])
+ addr, mask = self._split_addr_prefix(address)
- self.network = IPv4Network(address, strict=False)
+ IPv4Address.__init__(self, addr)
+ self.network = IPv4Network((addr, mask), strict=False)
+ self.netmask = self.network.netmask
self._prefixlen = self.network._prefixlen
- self.netmask = self.network.netmask
- self.hostmask = self.network.hostmask
+ @functools.cached_property
+ def hostmask(self):
+ return self.network.hostmask
def __str__(self):
return '%s/%d' % (self._string_from_ip_int(self._ip),
@@ -1435,20 +1443,7 @@ class IPv4Network(_BaseV4, _BaseNetwork):
ValueError: If strict is True and a network address is not
supplied.
"""
- # Constructing from a packed address or integer
- if isinstance(address, (int, bytes)):
- addr = address
- mask = self._max_prefixlen
- # Constructing from a tuple (addr, [mask])
- elif isinstance(address, tuple):
- addr = address[0]
- mask = address[1] if len(address) > 1 else self._max_prefixlen
- # Assume input argument to be string or any object representation
- # which converts into a formatted IP prefix string.
- else:
- args = _split_optional_netmask(address)
- addr = self._ip_int_from_string(args[0])
- mask = args[1] if len(args) == 2 else self._max_prefixlen
+ addr, mask = self._split_addr_prefix(address)
self.network_address = IPv4Address(addr)
self.netmask, self._prefixlen = self._make_netmask(mask)
@@ -1979,28 +1974,16 @@ class IPv6Address(_BaseV6, _BaseAddress):
class IPv6Interface(IPv6Address):
def __init__(self, address):
- if isinstance(address, (bytes, int)):
- IPv6Address.__init__(self, address)
- 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, mask = self._split_addr_prefix(address)
- addr = _split_optional_netmask(address)
- IPv6Address.__init__(self, addr[0])
- self.network = IPv6Network(address, strict=False)
+ IPv6Address.__init__(self, addr)
+ self.network = IPv6Network((addr, mask), strict=False)
self.netmask = self.network.netmask
self._prefixlen = self.network._prefixlen
- self.hostmask = self.network.hostmask
+
+ @functools.cached_property
+ def hostmask(self):
+ return self.network.hostmask
def __str__(self):
return '%s/%d' % (self._string_from_ip_int(self._ip),
@@ -2110,20 +2093,7 @@ class IPv6Network(_BaseV6, _BaseNetwork):
ValueError: If strict was True and a network address was not
supplied.
"""
- # Constructing from a packed address or integer
- if isinstance(address, (int, bytes)):
- addr = address
- mask = self._max_prefixlen
- # Constructing from a tuple (addr, [mask])
- elif isinstance(address, tuple):
- addr = address[0]
- mask = address[1] if len(address) > 1 else self._max_prefixlen
- # Assume input argument to be string or any object representation
- # which converts into a formatted IP prefix string.
- else:
- args = _split_optional_netmask(address)
- addr = self._ip_int_from_string(args[0])
- mask = args[1] if len(args) == 2 else self._max_prefixlen
+ addr, mask = self._split_addr_prefix(address)
self.network_address = IPv6Address(addr)
self.netmask, self._prefixlen = self._make_netmask(mask)