From 2093d2042cff3bc8a327c066fdd35f42620c8535 Mon Sep 17 00:00:00 2001 From: Alex Perry Date: Mon, 22 May 2017 16:19:34 -0700 Subject: [PATCH] bpo-27269: Treat ::FFFF: addresses as IPv4 for ordering and contains. --- Lib/ipaddress.py | 39 +++++++++++++++++++++++++------------- Lib/test/test_ipaddress.py | 7 +++++-- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 70746f8de85c09..f2d941aa68e8a3 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -376,8 +376,10 @@ def get_mixed_type_key(obj): """ if isinstance(obj, _BaseNetwork): + obj = obj.ipv4_mapped or obj return obj._get_networks_key() elif isinstance(obj, _BaseAddress): + obj = obj.ipv4_mapped or obj return obj._get_address_key() return NotImplemented @@ -423,6 +425,15 @@ def _check_int_address(self, address): raise AddressValueError(msg % (address, self._max_prefixlen, self._version)) + @property + def ipv4_mapped(self): + """Returns an IPv4 address, maybe mapped by RFC 5156 from ::ffff: + + Returns: + An IPv4Address instance or None + """ + return None + def _check_packed_address(self, address, expected_len): address_len = len(address) if address_len != expected_len: @@ -668,6 +679,8 @@ def __hash__(self): return hash(int(self.network_address) ^ int(self.netmask)) def __contains__(self, other): + if other._version == 6 and self._version == 4: + other = other.ipv4_mapped or other # always false if one is v4 and the other is v6. if self._version != other._version: return False @@ -1916,6 +1929,19 @@ def __init__(self, address): raise AddressValueError("Unexpected '/' in %r" % address) self._ip = self._ip_int_from_string(addr_str) + @property + def ipv4_mapped(self): + """Return the IPv4 mapped address. + + Returns: + If the IPv6 address is a v4 mapped address, return the + IPv4 mapped address. Return None otherwise. + + """ + if (self._ip >> 32) != 0xFFFF: + return None + return IPv4Address(self._ip & 0xFFFFFFFF) + @property def packed(self): """The binary representation of this address.""" @@ -2012,19 +2038,6 @@ def is_loopback(self): """ return self._ip == 1 - @property - def ipv4_mapped(self): - """Return the IPv4 mapped address. - - Returns: - If the IPv6 address is a v4 mapped address, return the - IPv4 mapped address. Return None otherwise. - - """ - if (self._ip >> 32) != 0xFFFF: - return None - return IPv4Address(self._ip & 0xFFFFFFFF) - @property def teredo(self): """Tuple of embedded teredo IPs. diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 5d9633024f7064..3e375ce81cd37f 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -583,7 +583,10 @@ class ComparisonTests(unittest.TestCase): v6net = ipaddress.IPv6Network(1) v6intf = ipaddress.IPv6Interface(1) - v4_addresses = [v4addr, v4intf] + v4mapaddr = ipaddress.IPv6Address('::ffff:0:1') + v4mapnet = ipaddress.IPv6Address('::ffff:0:1') + + v4_addresses = [v4addr, v4intf, v4mapaddr] v4_objects = v4_addresses + [v4net] v6_addresses = [v6addr, v6intf] v6_objects = v6_addresses + [v6net] @@ -684,7 +687,7 @@ def test_foreign_type_ordering(self): def test_mixed_type_key(self): # with get_mixed_type_key, you can sort addresses and network. - v4_ordered = [self.v4addr, self.v4net, self.v4intf] + v4_ordered = [self.v4addr, self.v4mapaddr, self.v4net, self.v4intf] v6_ordered = [self.v6addr, self.v6net, self.v6intf] self.assertEqual(v4_ordered, sorted(self.v4_objects, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy