diff options
author | Louis des Landes <louis@obsidian.com.au> | 2013-03-19 16:41:23 +1100 |
---|---|---|
committer | Louis des Landes <louis@obsidian.com.au> | 2013-03-19 16:41:23 +1100 |
commit | f884a6d43ca57f423a8bacb61b2bcbd51bdcbe76 (patch) | |
tree | 268bb520f52b28a9cc484fc6ba32f5afc241a3fc | |
parent | 328effb64e6dd575d7ba790941261f1efef102ba (diff) | |
download | netaddr-f884a6d43ca57f423a8bacb61b2bcbd51bdcbe76.tar.gz |
Add iscontiguous() and getRange() to IPSet
-rw-r--r-- | netaddr/ip/sets.py | 31 | ||||
-rw-r--r-- | netaddr/tests/2.x/ip/sets.txt | 22 | ||||
-rw-r--r-- | netaddr/tests/3.x/ip/sets.txt | 21 |
3 files changed, 74 insertions, 0 deletions
diff --git a/netaddr/ip/sets.py b/netaddr/ip/sets.py index 0107f74..f928c1b 100644 --- a/netaddr/ip/sets.py +++ b/netaddr/ip/sets.py @@ -627,3 +627,34 @@ class IPSet(object): return 'IPSet(%r)' % [str(c) for c in sorted(self._cidrs)] __str__ = __repr__ + + def iscontiguous(self): + """ + Note this method depends on ``iter_cidrs`` being sorted. + + :return: ``True`` if the ``IPSet`` object is contiguous. + """ + previous = self.iter_cidrs()[0][0] + for cidr in self.iter_cidrs(): + if cidr[0] != previous: + # This isn't contiguous + return False + previous = cidr[-1] + 1 + return True + + def getRange(self): + """ + Get the starting and ending IP of this set, assuming it is + contiguous. + Note this method depends on ``iter_cidrs`` being sorted. + + Raises ``ValueError`` if the set is not contiguous. + + :return: An ``IPRange`` if the IPSet is contiguous. + + """ + if self.iscontiguous(): + cidrs = self.iter_cidrs() + return IPRange(cidrs[0][0], cidrs[-1][-1]) + else: + raise ValueError("IPSet is not contiguous") diff --git a/netaddr/tests/2.x/ip/sets.txt b/netaddr/tests/2.x/ip/sets.txt index 661882a..b966300 100644 --- a/netaddr/tests/2.x/ip/sets.txt +++ b/netaddr/tests/2.x/ip/sets.txt @@ -437,6 +437,28 @@ And we're back to our original address. >>> s1 IPSet(['0.0.0.0/0']) +-------------------------------- +Convert an IP set to an IP Range +-------------------------------- +Sometimes you may want to convert an IPSet back to an IPRange. +>>> s1 = IPSet(['10.0.0.0/25', '10.0.0.128/25']) + +>>> s1.getRange() +IPRange('10.0.0.0', '10.0.0.255') + +This only works if the IPSet is contiguous +>>> s1.iscontiguous() +True +>>> s1.remove('10.0.0.16') +>>> s1 +IPSet(['10.0.0.0/28', '10.0.0.17/32', '10.0.0.18/31', '10.0.0.20/30', '10.0.0.24/29', '10.0.0.32/27', '10.0.0.64/26', '10.0.0.128/25']) +>>> s1.iscontiguous() +False +>>> s1.getRange() +Traceback (most recent call last): + File "<stdin>", line 1, in <module> +ValueError: IPSet is not contiguous + ---------------------- Pickling IPSet objects ---------------------- diff --git a/netaddr/tests/3.x/ip/sets.txt b/netaddr/tests/3.x/ip/sets.txt index 07c2548..4c83de7 100644 --- a/netaddr/tests/3.x/ip/sets.txt +++ b/netaddr/tests/3.x/ip/sets.txt @@ -485,3 +485,24 @@ Pickling of IPSet objects True }}} + +Convert an IP set to an IP Range + +{{{ + +>>> s1 = IPSet(['10.0.0.0/25', '10.0.0.128/25']) +>>> s1.getRange() +IPRange('10.0.0.0', '10.0.0.255') +>>> s1.iscontiguous() +True +>>> s1.remove('10.0.0.16') +>>> s1 +IPSet(['10.0.0.0/28', '10.0.0.17/32', '10.0.0.18/31', '10.0.0.20/30', '10.0.0.24/29', '10.0.0.32/27', '10.0.0.64/26', '10.0.0.128/25']) +>>> s1.iscontiguous() +False +>>> s1.getRange() +Traceback (most recent call last): + ... +ValueError: IPSet is not contiguous + +}}} |