v0.165.0
 1import ipaddress
 2
 3from plain.exceptions import ValidationError
 4
 5
 6def clean_ipv6_address(
 7    ip_str: str,
 8    unpack_ipv4: bool = False,
 9    error_message: str = "This is not a valid IPv6 address.",
10) -> str:
11    """
12    Clean an IPv6 address string.
13
14    Raise ValidationError if the address is invalid.
15
16    Replace the longest continuous zero-sequence with "::", remove leading
17    zeroes, and make sure all hextets are lowercase.
18
19    Args:
20        ip_str: A valid IPv6 address.
21        unpack_ipv4: if an IPv4-mapped address is found,
22        return the plain IPv4 address (default=False).
23        error_message: An error message used in the ValidationError.
24
25    Return a compressed IPv6 address or the same value.
26    """
27    try:
28        addr = ipaddress.IPv6Address(int(ipaddress.IPv6Address(ip_str)))
29    except ValueError:
30        raise ValidationError(error_message, code="invalid")
31
32    if unpack_ipv4 and addr.ipv4_mapped:
33        return str(addr.ipv4_mapped)
34    elif addr.ipv4_mapped:
35        return f"::ffff:{addr.ipv4_mapped!s}"
36
37    return str(addr)
38
39
40def is_valid_ipv6_address(ip_str: str) -> bool:
41    """
42    Return whether or not the `ip_str` string is a valid IPv6 address.
43    """
44    try:
45        ipaddress.IPv6Address(ip_str)
46    except ValueError:
47        return False
48    return True