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

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: New patch to work with 2.0.x branch. Added _hash_() method to BaseIP class for set() to work. 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
268 first = first._ip
269 last = last._ip
270 while first <= last: 270 while first <= last:
271 nbits = _count_righthand_zero_bits(first._ip, ip_bits) 271 nbits = _count_righthand_zero_bits(first, ip_bits)
272 current = None 272 current = None
273 while nbits >= 0: 273 while nbits >= 0:
274 addend = 2**nbits - 1 274 addend = 2**nbits - 1
275 current = first._ip + addend 275 current = first + addend
276 nbits -= 1 276 nbits -= 1
277 if ip(current) <= last: 277 if current <= last:
278 break 278 break
279 prefix = _get_prefix_length(first._ip, current, ip_bits) 279 prefix = _get_prefix_length(first, current, ip_bits)
280 networks.append(ipnet('%s/%s' % (first, prefix))) 280 net = ip(first)
281 if current == first._ALL_ONES: 281 net.prefixlen = prefix
282 networks.append(net)
283 if current == ip._ALL_ONES:
282 break 284 break
283 first = ip(current + 1) 285 first = current + 1
284 return networks 286 return networks
285 287
286 def _collapse_address_list_recursive(addresses): 288 def _collapse_address_list_recursive(addresses):
287 """Loops through the addresses, collapsing concurrent netblocks. 289 """Loops through the addresses, collapsing concurrent netblocks.
288 290
289 Example: 291 Example:
290 292
291 ip1 = IPv4('1.1.0.0/24') 293 ip1 = IPv4('1.1.0.0/24')
292 ip2 = IPv4('1.1.1.0/24') 294 ip2 = IPv4('1.1.1.0/24')
293 ip3 = IPv4('1.1.2.0/24') 295 ip3 = IPv4('1.1.2.0/24')
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 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')]) ->
337 [IPv4('1.1.0.0/23')] 339 [IPv4('1.1.0.0/23')]
338 340
339 Args: 341 Args:
340 addresses: A list of IPv4 or IPv6 objects. 342 addresses: A list of IPv4 or IPv6 objects.
341 343
342 Returns: 344 Returns:
343 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.
344 346
345 """ 347 """
346 _addresses = []
347 i = 0 348 i = 0
348 ip_bits = addresses[0]._max_prefixlen 349 addrs = []
349 # filter out IP addresses, dedup, and sort 350 ips = []
350 addrs = sorted(set([ip for ip in addresses if isinstance(ip, BaseIP)])) 351 nets = []
351 nets = sorted(set([ip for ip in addresses if isinstance(ip, BaseNet)])) 352 # split IP addresses and networks
352 353 for ip in addresses:
353 while i < len(addrs): 354 if isinstance(ip, BaseIP):
354 (first, last) = _find_address_range(addrs[i:]) 355 ips.append(ip)
355 i = addrs.index(last) + 1 356 elif ip._prefixlen == ip._max_prefixlen:
356 _addresses.extend( 357 ips.append(ip.ip)
357 [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))
358 368
359 return _collapse_address_list_recursive( 369 return _collapse_address_list_recursive(
360 sorted(_addresses + nets, key=BaseNet._get_networks_key)) 370 sorted(addrs + nets, key=BaseNet._get_networks_key))
361 371
362 # backwards compatibility 372 # backwards compatibility
363 CollapseAddrList = collapse_address_list 373 CollapseAddrList = collapse_address_list
364 374
365 # Test whether this Python implementation supports byte objects that 375 # Test whether this Python implementation supports byte objects that
366 # are not identical to str ones. 376 # are not identical to str ones.
367 # 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
368 # distinguish between packed representations and strings, for example 378 # distinguish between packed representations and strings, for example
369 # 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).
370 try: 380 try:
(...skipping 1411 matching lines...) Expand 10 before | Expand all | Expand 10 after
1782 """ 1792 """
1783 try: 1793 try:
1784 prefixlen = int(prefixlen) 1794 prefixlen = int(prefixlen)
1785 except ValueError: 1795 except ValueError:
1786 return False 1796 return False
1787 return 0 <= prefixlen <= 128 1797 return 0 <= prefixlen <= 128
1788 1798
1789 # backwards compatibility 1799 # backwards compatibility
1790 Subnet = subnet 1800 Subnet = subnet
1791 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