Kaydet (Commit) 1e71c534 authored tarafından Antoine Pitrou's avatar Antoine Pitrou

Issue #20826: Optimize ipaddress.collapse_addresses().

üst 824db30b
...@@ -253,7 +253,7 @@ def summarize_address_range(first, last): ...@@ -253,7 +253,7 @@ def summarize_address_range(first, last):
break break
def _collapse_addresses_recursive(addresses): def _collapse_addresses_internal(addresses):
"""Loops through the addresses, collapsing concurrent netblocks. """Loops through the addresses, collapsing concurrent netblocks.
Example: Example:
...@@ -263,7 +263,7 @@ def _collapse_addresses_recursive(addresses): ...@@ -263,7 +263,7 @@ def _collapse_addresses_recursive(addresses):
ip3 = IPv4Network('192.0.2.128/26') ip3 = IPv4Network('192.0.2.128/26')
ip4 = IPv4Network('192.0.2.192/26') ip4 = IPv4Network('192.0.2.192/26')
_collapse_addresses_recursive([ip1, ip2, ip3, ip4]) -> _collapse_addresses_internal([ip1, ip2, ip3, ip4]) ->
[IPv4Network('192.0.2.0/24')] [IPv4Network('192.0.2.0/24')]
This shouldn't be called directly; it is called via This shouldn't be called directly; it is called via
...@@ -277,28 +277,29 @@ def _collapse_addresses_recursive(addresses): ...@@ -277,28 +277,29 @@ def _collapse_addresses_recursive(addresses):
passed. passed.
""" """
while True: # First merge
last_addr = None to_merge = list(addresses)
ret_array = [] subnets = {}
optimized = False while to_merge:
net = to_merge.pop()
for cur_addr in addresses: supernet = net.supernet()
if not ret_array: existing = subnets.get(supernet)
last_addr = cur_addr if existing is None:
ret_array.append(cur_addr) subnets[supernet] = net
elif (cur_addr.network_address >= last_addr.network_address and elif existing != net:
cur_addr.broadcast_address <= last_addr.broadcast_address): # Merge consecutive subnets
optimized = True del subnets[supernet]
elif cur_addr == list(last_addr.supernet().subnets())[1]: to_merge.append(supernet)
ret_array[-1] = last_addr = last_addr.supernet() # Then iterate over resulting networks, skipping subsumed subnets
optimized = True last = None
else: for net in sorted(subnets.values()):
last_addr = cur_addr if last is not None:
ret_array.append(cur_addr) # Since they are sorted, last.network_address <= net.network_address
# is a given.
addresses = ret_array if last.broadcast_address >= net.broadcast_address:
if not optimized: continue
return addresses yield net
last = net
def collapse_addresses(addresses): def collapse_addresses(addresses):
...@@ -347,15 +348,13 @@ def collapse_addresses(addresses): ...@@ -347,15 +348,13 @@ def collapse_addresses(addresses):
# sort and dedup # sort and dedup
ips = sorted(set(ips)) ips = sorted(set(ips))
nets = sorted(set(nets))
while i < len(ips): while i < len(ips):
(first, last) = _find_address_range(ips[i:]) (first, last) = _find_address_range(ips[i:])
i = ips.index(last) + 1 i = ips.index(last) + 1
addrs.extend(summarize_address_range(first, last)) addrs.extend(summarize_address_range(first, last))
return iter(_collapse_addresses_recursive(sorted( return _collapse_addresses_internal(addrs + nets)
addrs + nets, key=_BaseNetwork._get_networks_key)))
def get_mixed_type_key(obj): def get_mixed_type_key(obj):
......
...@@ -84,6 +84,8 @@ Core and Builtins ...@@ -84,6 +84,8 @@ Core and Builtins
Library Library
------- -------
- Issue #20826: Optimize ipaddress.collapse_addresses().
- Issue #21487: Optimize ipaddress.summarize_address_range() and - Issue #21487: Optimize ipaddress.summarize_address_range() and
ipaddress.{IPv4Network,IPv6Network}.subnets(). ipaddress.{IPv4Network,IPv6Network}.subnets().
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment