mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-07 13:41:15 -07:00
Upgrade ipaddr from 2.1.11 to 2.2.0. Its now python 3 compatible
This commit is contained in:
parent
f24f4a4250
commit
137889dc9c
1 changed files with 150 additions and 87 deletions
237
lib/ipaddr.py
237
lib/ipaddr.py
|
@ -22,9 +22,14 @@ and networks.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = '2.1.11'
|
__version__ = '2.2.0'
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if sys.version_info > (3,):
|
||||||
|
long = int
|
||||||
|
xrange = range
|
||||||
|
|
||||||
IPV4LENGTH = 32
|
IPV4LENGTH = 32
|
||||||
IPV6LENGTH = 128
|
IPV6LENGTH = 128
|
||||||
|
@ -156,16 +161,19 @@ def _find_address_range(addresses):
|
||||||
addresses: a list of IPv4 or IPv6 addresses.
|
addresses: a list of IPv4 or IPv6 addresses.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A tuple containing the first and last IP addresses in the sequence.
|
A tuple containing the first and last IP addresses in the sequence,
|
||||||
|
and the index of the last IP address in the sequence.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
first = last = addresses[0]
|
first = last = addresses[0]
|
||||||
|
last_index = 0
|
||||||
for ip in addresses[1:]:
|
for ip in addresses[1:]:
|
||||||
if ip._ip == last._ip + 1:
|
if ip._ip == last._ip + 1:
|
||||||
last = ip
|
last = ip
|
||||||
|
last_index += 1
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
return (first, last)
|
return (first, last, last_index)
|
||||||
|
|
||||||
def _get_prefix_length(number1, number2, bits):
|
def _get_prefix_length(number1, number2, bits):
|
||||||
"""Get the number of leading bits that are same for two numbers.
|
"""Get the number of leading bits that are same for two numbers.
|
||||||
|
@ -358,8 +366,8 @@ def collapse_address_list(addresses):
|
||||||
nets = sorted(set(nets))
|
nets = sorted(set(nets))
|
||||||
|
|
||||||
while i < len(ips):
|
while i < len(ips):
|
||||||
(first, last) = _find_address_range(ips[i:])
|
(first, last, last_index) = _find_address_range(ips[i:])
|
||||||
i = ips.index(last) + 1
|
i += last_index + 1
|
||||||
addrs.extend(summarize_address_range(first, last))
|
addrs.extend(summarize_address_range(first, last))
|
||||||
|
|
||||||
return _collapse_address_list_recursive(sorted(
|
return _collapse_address_list_recursive(sorted(
|
||||||
|
@ -876,6 +884,26 @@ class _BaseNet(_IPAddrBase):
|
||||||
else:
|
else:
|
||||||
raise NetmaskValueError('Bit pattern does not match /1*0*/')
|
raise NetmaskValueError('Bit pattern does not match /1*0*/')
|
||||||
|
|
||||||
|
def _prefix_from_prefix_int(self, prefixlen):
|
||||||
|
"""Validate and return a prefix length integer.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prefixlen: An integer containing the prefix length.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The input, possibly converted from long to int.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
NetmaskValueError: If the input is not an integer, or out of range.
|
||||||
|
"""
|
||||||
|
if not isinstance(prefixlen, (int, long)):
|
||||||
|
raise NetmaskValueError('%r is not an integer' % prefixlen)
|
||||||
|
prefixlen = int(prefixlen)
|
||||||
|
if not (0 <= prefixlen <= self._max_prefixlen):
|
||||||
|
raise NetmaskValueError('%d is not a valid prefix length' %
|
||||||
|
prefixlen)
|
||||||
|
return prefixlen
|
||||||
|
|
||||||
def _prefix_from_prefix_string(self, prefixlen_str):
|
def _prefix_from_prefix_string(self, prefixlen_str):
|
||||||
"""Turn a prefix length string into an integer.
|
"""Turn a prefix length string into an integer.
|
||||||
|
|
||||||
|
@ -893,12 +921,10 @@ class _BaseNet(_IPAddrBase):
|
||||||
if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str):
|
if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
prefixlen = int(prefixlen_str)
|
prefixlen = int(prefixlen_str)
|
||||||
if not (0 <= prefixlen <= self._max_prefixlen):
|
|
||||||
raise ValueError
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise NetmaskValueError('%s is not a valid prefix length' %
|
raise NetmaskValueError('%s is not a valid prefix length' %
|
||||||
prefixlen_str)
|
prefixlen_str)
|
||||||
return prefixlen
|
return self._prefix_from_prefix_int(prefixlen)
|
||||||
|
|
||||||
def _prefix_from_ip_string(self, ip_str):
|
def _prefix_from_ip_string(self, ip_str):
|
||||||
"""Turn a netmask/hostmask string into a prefix length.
|
"""Turn a netmask/hostmask string into a prefix length.
|
||||||
|
@ -1239,6 +1265,11 @@ class IPv4Address(_BaseV4, _BaseIP):
|
||||||
"""
|
"""
|
||||||
_BaseV4.__init__(self, address)
|
_BaseV4.__init__(self, address)
|
||||||
|
|
||||||
|
# Efficient copy constructor.
|
||||||
|
if isinstance(address, IPv4Address):
|
||||||
|
self._ip = address._ip
|
||||||
|
return
|
||||||
|
|
||||||
# Efficient constructor from integer.
|
# Efficient constructor from integer.
|
||||||
if isinstance(address, (int, long)):
|
if isinstance(address, (int, long)):
|
||||||
self._ip = address
|
self._ip = address
|
||||||
|
@ -1279,29 +1310,32 @@ class IPv4Network(_BaseV4, _BaseNet):
|
||||||
"""Instantiate a new IPv4 network object.
|
"""Instantiate a new IPv4 network object.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
address: A string or integer representing the IP [& network].
|
address: The IPv4 network as a string, 2-tuple, or any format
|
||||||
'192.168.1.1/24'
|
supported by the IPv4Address constructor.
|
||||||
'192.168.1.1/255.255.255.0'
|
|
||||||
'192.168.1.1/0.0.0.255'
|
|
||||||
are all functionally the same in IPv4. Similarly,
|
|
||||||
'192.168.1.1'
|
|
||||||
'192.168.1.1/255.255.255.255'
|
|
||||||
'192.168.1.1/32'
|
|
||||||
are also functionaly equivalent. That is to say, failing to
|
|
||||||
provide a subnetmask will create an object with a mask of /32.
|
|
||||||
|
|
||||||
If the mask (portion after the / in the argument) is given in
|
Strings typically use CIDR format, such as '192.0.2.0/24'.
|
||||||
dotted quad form, it is treated as a netmask if it starts with a
|
If a dotted-quad is provided after the '/', it is treated as
|
||||||
non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it
|
a netmask if it starts with a nonzero bit (e.g. 255.0.0.0 == /8)
|
||||||
starts with a zero field (e.g. 0.255.255.255 == /8), with the
|
or a hostmask if it starts with a zero bit
|
||||||
single exception of an all-zero mask which is treated as a
|
(e.g. /0.0.0.255 == /8), with the single exception of an all-zero
|
||||||
netmask == /0. If no mask is given, a default of /32 is used.
|
mask which is treated as /0.
|
||||||
|
|
||||||
Additionally, an integer can be passed, so
|
The 2-tuple format consists of an (ip, prefixlen), where ip is any
|
||||||
IPv4Network('192.168.1.1') == IPv4Network(3232235777).
|
format recognized by the IPv4Address constructor, and prefixlen is
|
||||||
or, more generally
|
an integer from 0 through 32.
|
||||||
IPv4Network(int(IPv4Network('192.168.1.1'))) ==
|
|
||||||
IPv4Network('192.168.1.1')
|
A plain IPv4 address (in any format) will be forwarded to the
|
||||||
|
IPv4Address constructor, with an implied prefixlen of 32.
|
||||||
|
|
||||||
|
For example, the following inputs are equivalent:
|
||||||
|
IPv4Network('192.0.2.1/32')
|
||||||
|
IPv4Network('192.0.2.1/255.255.255.255')
|
||||||
|
IPv4Network('192.0.2.1')
|
||||||
|
IPv4Network(0xc0000201)
|
||||||
|
IPv4Network(IPv4Address('192.0.2.1'))
|
||||||
|
IPv4Network(('192.0.2.1', 32))
|
||||||
|
IPv4Network((0xc0000201, 32))
|
||||||
|
IPv4Network((IPv4Address('192.0.2.1'), 32))
|
||||||
|
|
||||||
strict: A boolean. If true, ensure that we have been passed
|
strict: A boolean. If true, ensure that we have been passed
|
||||||
A true network address, eg, 192.168.1.0/24 and not an
|
A true network address, eg, 192.168.1.0/24 and not an
|
||||||
|
@ -1318,41 +1352,51 @@ class IPv4Network(_BaseV4, _BaseNet):
|
||||||
_BaseNet.__init__(self, address)
|
_BaseNet.__init__(self, address)
|
||||||
_BaseV4.__init__(self, address)
|
_BaseV4.__init__(self, address)
|
||||||
|
|
||||||
# Constructing from an integer or packed bytes.
|
# Constructing from a single IP address.
|
||||||
if isinstance(address, (int, long, Bytes)):
|
if isinstance(address, (int, long, Bytes, IPv4Address)):
|
||||||
self.ip = IPv4Address(address)
|
self.ip = IPv4Address(address)
|
||||||
self._ip = self.ip._ip
|
self._ip = self.ip._ip
|
||||||
self._prefixlen = self._max_prefixlen
|
self._prefixlen = self._max_prefixlen
|
||||||
self.netmask = IPv4Address(self._ALL_ONES)
|
self.netmask = IPv4Address(self._ALL_ONES)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Assume input argument to be string or any object representation
|
# Constructing from an (ip, prefixlen) tuple.
|
||||||
# which converts into a formatted IP prefix string.
|
if isinstance(address, tuple):
|
||||||
addr = str(address).split('/')
|
|
||||||
|
|
||||||
if len(addr) > 2:
|
|
||||||
raise AddressValueError(address)
|
|
||||||
|
|
||||||
self._ip = self._ip_int_from_string(addr[0])
|
|
||||||
self.ip = IPv4Address(self._ip)
|
|
||||||
|
|
||||||
if len(addr) == 2:
|
|
||||||
try:
|
try:
|
||||||
# Check for a netmask in prefix length form.
|
ip, prefixlen = address
|
||||||
self._prefixlen = self._prefix_from_prefix_string(addr[1])
|
except ValueError:
|
||||||
except NetmaskValueError:
|
raise AddressValueError(address)
|
||||||
# Check for a netmask or hostmask in dotted-quad form.
|
self.ip = IPv4Address(ip)
|
||||||
# This may raise NetmaskValueError.
|
self._ip = self.ip._ip
|
||||||
self._prefixlen = self._prefix_from_ip_string(addr[1])
|
self._prefixlen = self._prefix_from_prefix_int(prefixlen)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self._prefixlen = self._max_prefixlen
|
# Assume input argument to be string or any object representation
|
||||||
|
# which converts into a formatted IP prefix string.
|
||||||
|
addr = str(address).split('/')
|
||||||
|
|
||||||
|
if len(addr) > 2:
|
||||||
|
raise AddressValueError(address)
|
||||||
|
|
||||||
|
self._ip = self._ip_int_from_string(addr[0])
|
||||||
|
self.ip = IPv4Address(self._ip)
|
||||||
|
|
||||||
|
if len(addr) == 2:
|
||||||
|
try:
|
||||||
|
# Check for a netmask in prefix length form.
|
||||||
|
self._prefixlen = self._prefix_from_prefix_string(addr[1])
|
||||||
|
except NetmaskValueError:
|
||||||
|
# Check for a netmask or hostmask in dotted-quad form.
|
||||||
|
# This may raise NetmaskValueError.
|
||||||
|
self._prefixlen = self._prefix_from_ip_string(addr[1])
|
||||||
|
else:
|
||||||
|
self._prefixlen = self._max_prefixlen
|
||||||
|
|
||||||
self.netmask = IPv4Address(self._ip_int_from_prefix(self._prefixlen))
|
self.netmask = IPv4Address(self._ip_int_from_prefix(self._prefixlen))
|
||||||
|
|
||||||
if strict:
|
if strict:
|
||||||
if self.ip != self.network:
|
if self.ip != self.network:
|
||||||
raise ValueError('%s has host bits set' %
|
raise ValueError('%s has host bits set' % self.ip)
|
||||||
self.ip)
|
|
||||||
if self._prefixlen == (self._max_prefixlen - 1):
|
if self._prefixlen == (self._max_prefixlen - 1):
|
||||||
self.iterhosts = self.__iter__
|
self.iterhosts = self.__iter__
|
||||||
|
|
||||||
|
@ -1447,7 +1491,7 @@ class _BaseV6(object):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Now, parse the hextets into a 128-bit integer.
|
# Now, parse the hextets into a 128-bit integer.
|
||||||
ip_int = 0L
|
ip_int = long(0)
|
||||||
for i in xrange(parts_hi):
|
for i in xrange(parts_hi):
|
||||||
ip_int <<= 16
|
ip_int <<= 16
|
||||||
ip_int |= self._parse_hextet(parts[i])
|
ip_int |= self._parse_hextet(parts[i])
|
||||||
|
@ -1752,6 +1796,11 @@ class IPv6Address(_BaseV6, _BaseIP):
|
||||||
"""
|
"""
|
||||||
_BaseV6.__init__(self, address)
|
_BaseV6.__init__(self, address)
|
||||||
|
|
||||||
|
# Efficient copy constructor.
|
||||||
|
if isinstance(address, IPv6Address):
|
||||||
|
self._ip = address._ip
|
||||||
|
return
|
||||||
|
|
||||||
# Efficient constructor from integer.
|
# Efficient constructor from integer.
|
||||||
if isinstance(address, (int, long)):
|
if isinstance(address, (int, long)):
|
||||||
self._ip = address
|
self._ip = address
|
||||||
|
@ -1771,9 +1820,6 @@ class IPv6Address(_BaseV6, _BaseIP):
|
||||||
# Assume input argument to be string or any object representation
|
# Assume input argument to be string or any object representation
|
||||||
# which converts into a formatted IP string.
|
# which converts into a formatted IP string.
|
||||||
addr_str = str(address)
|
addr_str = str(address)
|
||||||
if not addr_str:
|
|
||||||
raise AddressValueError('')
|
|
||||||
|
|
||||||
self._ip = self._ip_int_from_string(addr_str)
|
self._ip = self._ip_int_from_string(addr_str)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1793,28 +1839,34 @@ class IPv6Network(_BaseV6, _BaseNet):
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, address, strict=False):
|
def __init__(self, address, strict=False):
|
||||||
"""Instantiate a new IPv6 Network object.
|
"""Instantiate a new IPv6 network object.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
address: A string or integer representing the IPv6 network or the IP
|
address: The IPv6 network as a string, 2-tuple, or any format
|
||||||
and prefix/netmask.
|
supported by the IPv6Address constructor.
|
||||||
'2001:4860::/128'
|
|
||||||
'2001:4860:0000:0000:0000:0000:0000:0000/128'
|
|
||||||
'2001:4860::'
|
|
||||||
are all functionally the same in IPv6. That is to say,
|
|
||||||
failing to provide a subnetmask will create an object with
|
|
||||||
a mask of /128.
|
|
||||||
|
|
||||||
Additionally, an integer can be passed, so
|
Strings should be in CIDR format, such as '2001:db8::/32'.
|
||||||
IPv6Network('2001:4860::') ==
|
|
||||||
IPv6Network(42541956101370907050197289607612071936L).
|
The 2-tuple format consists of an (ip, prefixlen), where ip is any
|
||||||
or, more generally
|
format recognized by the IPv6Address constructor, and prefixlen is
|
||||||
IPv6Network(IPv6Network('2001:4860::')._ip) ==
|
an integer from 0 through 128.
|
||||||
IPv6Network('2001:4860::')
|
|
||||||
|
A plain IPv6 address (in any format) will be forwarded to the
|
||||||
|
IPv6Address constructor, with an implied prefixlen of 128.
|
||||||
|
|
||||||
|
For example, the following inputs are equivalent:
|
||||||
|
IPv6Network('2001:db8::/128')
|
||||||
|
IPv6Network('2001:db8:0:0:0:0:0:0/128')
|
||||||
|
IPv6Network('2001:db8::')
|
||||||
|
IPv6Network(0x20010db8 << 96)
|
||||||
|
IPv6Network(IPv6Address('2001:db8::'))
|
||||||
|
IPv6Network(('2001:db8::', 128))
|
||||||
|
IPv6Network((0x20010db8 << 96, 128))
|
||||||
|
IPv6Network((IPv6Address('2001:db8::'), 128))
|
||||||
|
|
||||||
strict: A boolean. If true, ensure that we have been passed
|
strict: A boolean. If true, ensure that we have been passed
|
||||||
A true network address, eg, 192.168.1.0/24 and not an
|
A true network address, eg, 2001:db8::/32 and not an
|
||||||
IP address on a network, eg, 192.168.1.1/24.
|
IP address on a network, eg, 2001:db8::1/32.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
AddressValueError: If address isn't a valid IPv6 address.
|
AddressValueError: If address isn't a valid IPv6 address.
|
||||||
|
@ -1827,29 +1879,40 @@ class IPv6Network(_BaseV6, _BaseNet):
|
||||||
_BaseNet.__init__(self, address)
|
_BaseNet.__init__(self, address)
|
||||||
_BaseV6.__init__(self, address)
|
_BaseV6.__init__(self, address)
|
||||||
|
|
||||||
# Constructing from an integer or packed bytes.
|
# Constructing from a single IP address.
|
||||||
if isinstance(address, (int, long, Bytes)):
|
if isinstance(address, (int, long, Bytes, IPv6Address)):
|
||||||
self.ip = IPv6Address(address)
|
self.ip = IPv6Address(address)
|
||||||
self._ip = self.ip._ip
|
self._ip = self.ip._ip
|
||||||
self._prefixlen = self._max_prefixlen
|
self._prefixlen = self._max_prefixlen
|
||||||
self.netmask = IPv6Address(self._ALL_ONES)
|
self.netmask = IPv6Address(self._ALL_ONES)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Assume input argument to be string or any object representation
|
# Constructing from an (ip, prefixlen) tuple.
|
||||||
# which converts into a formatted IP prefix string.
|
if isinstance(address, tuple):
|
||||||
addr = str(address).split('/')
|
try:
|
||||||
|
ip, prefixlen = address
|
||||||
|
except ValueError:
|
||||||
|
raise AddressValueError(address)
|
||||||
|
self.ip = IPv6Address(ip)
|
||||||
|
self._ip = self.ip._ip
|
||||||
|
self._prefixlen = self._prefix_from_prefix_int(prefixlen)
|
||||||
|
|
||||||
if len(addr) > 2:
|
|
||||||
raise AddressValueError(address)
|
|
||||||
|
|
||||||
self._ip = self._ip_int_from_string(addr[0])
|
|
||||||
self.ip = IPv6Address(self._ip)
|
|
||||||
|
|
||||||
if len(addr) == 2:
|
|
||||||
# This may raise NetmaskValueError
|
|
||||||
self._prefixlen = self._prefix_from_prefix_string(addr[1])
|
|
||||||
else:
|
else:
|
||||||
self._prefixlen = self._max_prefixlen
|
# Assume input argument to be string or any object representation
|
||||||
|
# which converts into a formatted IP prefix string.
|
||||||
|
addr = str(address).split('/')
|
||||||
|
|
||||||
|
if len(addr) > 2:
|
||||||
|
raise AddressValueError(address)
|
||||||
|
|
||||||
|
self._ip = self._ip_int_from_string(addr[0])
|
||||||
|
self.ip = IPv6Address(self._ip)
|
||||||
|
|
||||||
|
if len(addr) == 2:
|
||||||
|
# This may raise NetmaskValueError
|
||||||
|
self._prefixlen = self._prefix_from_prefix_string(addr[1])
|
||||||
|
else:
|
||||||
|
self._prefixlen = self._max_prefixlen
|
||||||
|
|
||||||
self.netmask = IPv6Address(self._ip_int_from_prefix(self._prefixlen))
|
self.netmask = IPv6Address(self._ip_int_from_prefix(self._prefixlen))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue