diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2015-01-18 22:41:32 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2015-01-18 22:41:32 (GMT) |
commit | b53f0fbf96ec0b1f9ad7ddad5e9480d17e48e27a (patch) | |
tree | 80bcc8ef0106a6379e3a646984ca622771cacfe7 | |
parent | 1202a4733e6ffbf3149425aae14f7c4eeeb115c0 (diff) | |
download | cpython-b53f0fbf96ec0b1f9ad7ddad5e9480d17e48e27a.zip cpython-b53f0fbf96ec0b1f9ad7ddad5e9480d17e48e27a.tar.gz cpython-b53f0fbf96ec0b1f9ad7ddad5e9480d17e48e27a.tar.bz2 |
Issue #23266: Restore the performance of ipaddress.collapse_addresses() whith
duplicated addresses and simplify the code.
-rw-r--r-- | Lib/ipaddress.py | 36 | ||||
-rw-r--r-- | Lib/test/test_ipaddress.py | 14 |
2 files changed, 25 insertions, 25 deletions
diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index ce6bf0c..2ba98d8 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -164,25 +164,23 @@ def _split_optional_netmask(address): def _find_address_range(addresses): - """Find a sequence of IPv#Address. + """Find a sequence of sorted deduplicated IPv#Address. Args: addresses: a list of IPv#Address objects. - Returns: - A tuple containing the first and last IP addresses in the sequence, - and the number of distinct IP addresses in the sequence. + Yields: + A tuple containing the first and last IP addresses in the sequence. """ - first = last = addresses[0] - i = 1 - for ip in addresses[1:]: - if ip._ip == last._ip + 1: - last = ip - i += 1 - else: - break - return (first, last, i) + it = iter(addresses) + first = last = next(it) + for ip in it: + if ip._ip != last._ip + 1: + yield first, last + first = ip + last = ip + yield first, last def _count_righthand_zero_bits(number, bits): @@ -323,7 +321,6 @@ def collapse_addresses(addresses): TypeError: If passed a list of mixed version objects. """ - i = 0 addrs = [] ips = [] nets = [] @@ -349,14 +346,13 @@ def collapse_addresses(addresses): ip, nets[-1])) nets.append(ip) - # sort - ips = sorted(ips) + # sort and dedup + ips = sorted(set(ips)) # find consecutive address ranges in the sorted sequence and summarize them - while i < len(ips): - (first, last, items) = _find_address_range(ips[i:]) - i = items + i - addrs.extend(summarize_address_range(first, last)) + if ips: + for first, last in _find_address_range(ips): + addrs.extend(summarize_address_range(first, last)) return _collapse_addresses_internal(addrs + nets) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 95518af..5ec2cd4 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -790,11 +790,15 @@ class IpaddrUnitTest(unittest.TestCase): 2 ** ipaddress.IPV6LENGTH) def testInternals(self): - first, last, nitems = ipaddress._find_address_range([ - ipaddress.IPv4Address('10.10.10.10'), - ipaddress.IPv4Address('10.10.10.12')]) - self.assertEqual(first, last) - self.assertEqual(nitems, 1) + ip1 = ipaddress.IPv4Address('10.10.10.10') + ip2 = ipaddress.IPv4Address('10.10.10.11') + ip3 = ipaddress.IPv4Address('10.10.10.12') + self.assertEqual(list(ipaddress._find_address_range([ip1])), + [(ip1, ip1)]) + self.assertEqual(list(ipaddress._find_address_range([ip1, ip3])), + [(ip1, ip1), (ip3, ip3)]) + self.assertEqual(list(ipaddress._find_address_range([ip1, ip2, ip3])), + [(ip1, ip3)]) self.assertEqual(128, ipaddress._count_righthand_zero_bits(0, 128)) self.assertEqual("IPv4Network('1.2.3.0/24')", repr(self.ipv4_network)) |