Turn an IPv6 ip_str into an integer. Args: ip_str: A string, the IPv6 ip_str. Returns: An int, the IPv6 address Raises: AddressValueError: if ip_str isn't a valid IPv6 Address.
(cls, ip_str)
| 1647 | |
| 1648 | @classmethod |
| 1649 | def _ip_int_from_string(cls, ip_str): |
| 1650 | """Turn an IPv6 ip_str into an integer. |
| 1651 | |
| 1652 | Args: |
| 1653 | ip_str: A string, the IPv6 ip_str. |
| 1654 | |
| 1655 | Returns: |
| 1656 | An int, the IPv6 address |
| 1657 | |
| 1658 | Raises: |
| 1659 | AddressValueError: if ip_str isn't a valid IPv6 Address. |
| 1660 | |
| 1661 | """ |
| 1662 | if not ip_str: |
| 1663 | raise AddressValueError('Address cannot be empty') |
| 1664 | if len(ip_str) > 45: |
| 1665 | shorten = ip_str |
| 1666 | if len(shorten) > 100: |
| 1667 | shorten = f'{ip_str[:45]}({len(ip_str)-90} chars elided){ip_str[-45:]}' |
| 1668 | raise AddressValueError(f"At most 45 characters expected in " |
| 1669 | f"{shorten!r}") |
| 1670 | |
| 1671 | # We want to allow more parts than the max to be 'split' |
| 1672 | # to preserve the correct error message when there are |
| 1673 | # too many parts combined with '::' |
| 1674 | _max_parts = cls._HEXTET_COUNT + 1 |
| 1675 | parts = ip_str.split(':', maxsplit=_max_parts) |
| 1676 | |
| 1677 | # An IPv6 address needs at least 2 colons (3 parts). |
| 1678 | _min_parts = 3 |
| 1679 | if len(parts) < _min_parts: |
| 1680 | msg = "At least %d parts expected in %r" % (_min_parts, ip_str) |
| 1681 | raise AddressValueError(msg) |
| 1682 | |
| 1683 | # If the address has an IPv4-style suffix, convert it to hexadecimal. |
| 1684 | if '.' in parts[-1]: |
| 1685 | try: |
| 1686 | ipv4_int = IPv4Address(parts.pop())._ip |
| 1687 | except AddressValueError as exc: |
| 1688 | raise AddressValueError("%s in %r" % (exc, ip_str)) from None |
| 1689 | parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF)) |
| 1690 | parts.append('%x' % (ipv4_int & 0xFFFF)) |
| 1691 | |
| 1692 | # An IPv6 address can't have more than 8 colons (9 parts). |
| 1693 | # The extra colon comes from using the "::" notation for a single |
| 1694 | # leading or trailing zero part. |
| 1695 | if len(parts) > _max_parts: |
| 1696 | msg = "At most %d colons permitted in %r" % (_max_parts-1, ip_str) |
| 1697 | raise AddressValueError(msg) |
| 1698 | |
| 1699 | # Disregarding the endpoints, find '::' with nothing in between. |
| 1700 | # This indicates that a run of zeroes has been skipped. |
| 1701 | skip_index = None |
| 1702 | for i in range(1, len(parts) - 1): |
| 1703 | if not parts[i]: |
| 1704 | if skip_index is not None: |
| 1705 | # Can't have more than one '::' |
| 1706 | msg = "At most one '::' permitted in %r" % ip_str |
no test coverage detected