Changeset - 9c7849a1fdfd
[Not reviewed]
default
0 1 0
Mads Kiilerich - 7 years ago 2019-01-05 16:47:08
mads@kiilerich.com
Grafted from: 06cad93246fd
tests: fix doctest for summarize_address_range - it is sensitive to linebreaks
1 file changed with 2 insertions and 4 deletions:
0 comments (0 inline, 0 general)
kallithea/lib/ipaddr.py
Show inline comments
 
@@ -161,100 +161,98 @@ def _find_address_range(addresses):
 
    for ip in addresses[1:]:
 
        if ip._ip == last._ip + 1:
 
            last = ip
 
        else:
 
            break
 
    return (first, last)
 

	
 

	
 
def _get_prefix_length(number1, number2, bits):
 
    """Get the number of leading bits that are same for two numbers.
 

	
 
    Args:
 
        number1: an integer.
 
        number2: another integer.
 
        bits: the maximum number of bits to compare.
 

	
 
    Returns:
 
        The number of leading bits that are the same for two numbers.
 

	
 
    """
 
    for i in range(bits):
 
        if number1 >> i == number2 >> i:
 
            return bits - i
 
    return 0
 

	
 

	
 
def _count_righthand_zero_bits(number, bits):
 
    """Count the number of zero bits on the right hand side.
 

	
 
    Args:
 
        number: an integer.
 
        bits: maximum number of bits to count.
 

	
 
    Returns:
 
        The number of zero bits on the right hand side of the number.
 

	
 
    """
 
    if number == 0:
 
        return bits
 
    for i in range(bits):
 
        if (number >> i) % 2:
 
            return i
 

	
 

	
 
def summarize_address_range(first, last):
 
    """Summarize a network range given the first and last IP addresses.
 

	
 
    Example:
 
        >>> summarize_address_range(IPv4Address('1.1.1.0'),
 
            IPv4Address('1.1.1.130'))
 
        [IPv4Network('1.1.1.0/25'), IPv4Network('1.1.1.128/31'),
 
        IPv4Network('1.1.1.130/32')]
 
        >>> summarize_address_range(IPv4Address('1.1.1.0'), IPv4Address('1.1.1.130'))
 
        [IPv4Network('1.1.1.0/25'), IPv4Network('1.1.1.128/31'), IPv4Network('1.1.1.130/32')]
 

	
 
    Args:
 
        first: the first IPv4Address or IPv6Address in the range.
 
        last: the last IPv4Address or IPv6Address in the range.
 

	
 
    Returns:
 
        The address range collapsed to a list of IPv4Network's or
 
        IPv6Network's.
 

	
 
    Raise:
 
        TypeError:
 
            If the first and last objects are not IP addresses.
 
            If the first and last objects are not the same version.
 
        ValueError:
 
            If the last object is not greater than the first.
 
            If the version is not 4 or 6.
 

	
 
    """
 
    if not (isinstance(first, _BaseIP) and isinstance(last, _BaseIP)):
 
        raise TypeError('first and last must be IP addresses, not networks')
 
    if first.version != last.version:
 
        raise TypeError("%s and %s are not of the same version" % (
 
                str(first), str(last)))
 
    if first > last:
 
        raise ValueError('last IP address must be greater than first')
 

	
 
    networks = []
 

	
 
    if first.version == 4:
 
        ip = IPv4Network
 
    elif first.version == 6:
 
        ip = IPv6Network
 
    else:
 
        raise ValueError('unknown IP version')
 

	
 
    ip_bits = first._max_prefixlen
 
    first_int = first._ip
 
    last_int = last._ip
 
    while first_int <= last_int:
 
        nbits = _count_righthand_zero_bits(first_int, ip_bits)
 
        current = None
 
        while nbits >= 0:
 
            addend = 2 ** nbits - 1
 
            current = first_int + addend
 
            nbits -= 1
 
            if current <= last_int:
 
                break
 
        prefix = _get_prefix_length(first_int, current, ip_bits)
0 comments (0 inline, 0 general)