Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(52)

Delta Between Two Patch Sets: ipaddr.py

Issue 67107: collapse_address_list is too slow SVN Base: http://ipaddr-py.googlecode.com/svn/trunk/
Left Patch Set: Up to 2x faster version of previous patch. Created 3 months, 2 weeks ago
Right Patch Set: Fixes for comments on Patch Set 6 Created 3 months, 2 weeks ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # 2 #
3 # Copyright 2007 Google Inc. 3 # Copyright 2007 Google Inc.
4 # Licensed to PSF under a Contributor Agreement. 4 # Licensed to PSF under a Contributor Agreement.
5 # 5 #
6 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License. 7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at 8 # You may obtain a copy of the License at
9 # 9 #
10 # http://www.apache.org/licenses/LICENSE-2.0 10 # http://www.apache.org/licenses/LICENSE-2.0
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 IPTypeError: 242 IPTypeError:
243 If the first and last objects are not IP addresses. 243 If the first and last objects are not IP addresses.
244 If the first and last objects are not the same version. 244 If the first and last objects are not the same version.
245 ValueError: 245 ValueError:
246 If the last object is not greater than the first. 246 If the last object is not greater than the first.
247 If the version is not 4 or 6. 247 If the version is not 4 or 6.
248 248
249 """ 249 """
250 250
251 if not (isinstance(first, BaseIP) and isinstance(last, BaseIP)): 251 if not (isinstance(first, BaseIP) and isinstance(last, BaseIP)):
252 raise IPTypeError("first and last must be IP addresses not networks.") 252 raise IPTypeError("first and last must be IP addresses, not networks")
253 if first.version != last.version: 253 if first.version != last.version:
254 raise IPTypeError("IP addresses must be same version") 254 raise IPTypeError("IP addresses must be same version")
255 if first > last: 255 if first > last:
256 raise ValueError("last IP address must be greater than first") 256 raise ValueError("last IP address must be greater than first")
257 257
258 networks = [] 258 networks = []
259 259
260 if first.version == 4: 260 if first.version == 4:
261 ipnet = IPv4Network 261 ip = IPv4Network
262 ip = IPv4Address
263 elif first.version == 6: 262 elif first.version == 6:
264 ipnet = IPv6Network 263 ip = IPv6Network
265 ip = IPv6Address
266 else: 264 else:
267 raise ValueError("unknown IP version") 265 raise ValueError("unknown IP version")
268 266
269 ip_bits = first._max_prefixlen 267 ip_bits = first._max_prefixlen
270 first = first._ip 268 first = first._ip
271 last = last._ip 269 last = last._ip
272 while first <= last: 270 while first <= last:
273 nbits = _count_righthand_zero_bits(first, ip_bits) 271 nbits = _count_righthand_zero_bits(first, ip_bits)
274 current = None 272 current = None
275 while nbits >= 0: 273 while nbits >= 0:
276 addend = 2**nbits - 1 274 addend = 2**nbits - 1
277 current = first + addend 275 current = first + addend
278 nbits -= 1 276 nbits -= 1
279 if current <= last: 277 if current <= last:
280 break 278 break
281 prefix = _get_prefix_length(first, current, ip_bits) 279 prefix = _get_prefix_length(first, current, ip_bits)
282 net = ipnet(first) 280 net = ip(first)
283 net.prefixlen = prefix 281 net.prefixlen = prefix
284 networks.append(net) 282 networks.append(net)
285 if current == ip._ALL_ONES: 283 if current == ip._ALL_ONES:
286 break 284 break
287 first = current + 1 285 first = current + 1
288 return networks 286 return networks
289 287
290 def _collapse_address_list_recursive(addresses): 288 def _collapse_address_list_recursive(addresses):
291 """Loops through the addresses, collapsing concurrent netblocks. 289 """Loops through the addresses, collapsing concurrent netblocks.
292 290
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 collapse_address_list([IPv4('1.1.0.0/24'), IPv4('1.1.1.0/24')]) -> 338 collapse_address_list([IPv4('1.1.0.0/24'), IPv4('1.1.1.0/24')]) ->
341 [IPv4('1.1.0.0/23')] 339 [IPv4('1.1.0.0/23')]
342 340
343 Args: 341 Args:
344 addresses: A list of IPv4 or IPv6 objects. 342 addresses: A list of IPv4 or IPv6 objects.
345 343
346 Returns: 344 Returns:
347 A list of IPv4 or IPv6 objects depending on what we were passed. 345 A list of IPv4 or IPv6 objects depending on what we were passed.
348 346
349 """ 347 """
350 _addresses = []
351 i = 0 348 i = 0
352 ip_bits = addresses[0]._max_prefixlen 349 addrs = []
353 # filter out IP addresses, dedup, and sort 350 ips = []
354 addrs = sorted(set([ip for ip in addresses if isinstance(ip, BaseIP)])) 351 nets = []
355 nets = sorted(set([ip for ip in addresses if isinstance(ip, BaseNet)])) 352 # split IP addresses and networks
356 353 for ip in addresses:
357 while i < len(addrs): 354 if isinstance(ip, BaseIP):
358 (first, last) = _find_address_range(addrs[i:]) 355 ips.append(ip)
359 i = addrs.index(last) + 1 356 elif ip._prefixlen == ip._max_prefixlen:
360 _addresses.extend( 357 ips.append(ip.ip)
361 [IP(ip) for ip in summarize_address_range(first, last)]) 358 else:
359 nets.append(ip)
360 # sort and dedup
361 ips = sorted(set(ips))
362 nets = sorted(set(nets))
363
364 while i < len(ips):
365 (first, last) = _find_address_range(ips[i:])
366 i = ips.index(last) + 1
367 addrs.extend(summarize_address_range(first, last))
362 368
363 return _collapse_address_list_recursive( 369 return _collapse_address_list_recursive(
364 sorted(_addresses + nets, key=BaseNet._get_networks_key)) 370 sorted(addrs + nets, key=BaseNet._get_networks_key))
365 371
366 # backwards compatibility 372 # backwards compatibility
367 CollapseAddrList = collapse_address_list 373 CollapseAddrList = collapse_address_list
368 374
369 # Test whether this Python implementation supports byte objects that 375 # Test whether this Python implementation supports byte objects that
370 # are not identical to str ones. 376 # are not identical to str ones.
371 # We need to exclude platforms where bytes == str so that we can 377 # We need to exclude platforms where bytes == str so that we can
372 # distinguish between packed representations and strings, for example 378 # distinguish between packed representations and strings, for example
373 # b'12::' (the IPv4 address 49.50.58.58) and '12::' (an IPv6 address). 379 # b'12::' (the IPv4 address 49.50.58.58) and '12::' (an IPv6 address).
374 try: 380 try:
(...skipping 1411 matching lines...) Expand 10 before | Expand all | Expand 10 after
1786 """ 1792 """
1787 try: 1793 try:
1788 prefixlen = int(prefixlen) 1794 prefixlen = int(prefixlen)
1789 except ValueError: 1795 except ValueError:
1790 return False 1796 return False
1791 return 0 <= prefixlen <= 128 1797 return 0 <= prefixlen <= 128
1792 1798
1793 # backwards compatibility 1799 # backwards compatibility
1794 Subnet = subnet 1800 Subnet = subnet
1795 Supernet = supernet 1801 Supernet = supernet
LEFTRIGHT
« no previous file | ipaddr_test.py » ('j') | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld r497