diff options
author | Chris St. Pierre <chris.a.st.pierre@gmail.com> | 2013-02-05 12:13:20 -0500 |
---|---|---|
committer | Chris St. Pierre <chris.a.st.pierre@gmail.com> | 2013-02-14 15:12:20 -0500 |
commit | 9bec4d6bbab599bee72256c7e09fe214cb849a1b (patch) | |
tree | cd2c5dac3463e6f505b0d522036ee7ac204c3276 /src/lib/Bcfg2/Utils.py | |
parent | e989e62b24479fac99e607d9e4fb3a292bd20418 (diff) | |
download | bcfg2-9bec4d6bbab599bee72256c7e09fe214cb849a1b.tar.gz bcfg2-9bec4d6bbab599bee72256c7e09fe214cb849a1b.tar.bz2 bcfg2-9bec4d6bbab599bee72256c7e09fe214cb849a1b.zip |
abstracted similar digit range classes in POSIXUsers/GroupPatterns into Bcfg2.Utils
Diffstat (limited to 'src/lib/Bcfg2/Utils.py')
-rw-r--r-- | src/lib/Bcfg2/Utils.py | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/lib/Bcfg2/Utils.py b/src/lib/Bcfg2/Utils.py new file mode 100644 index 000000000..ba17e1a63 --- /dev/null +++ b/src/lib/Bcfg2/Utils.py @@ -0,0 +1,67 @@ +""" Miscellaneous useful utility functions, classes, etc., that are +used by both client and server. Stuff that doesn't fit anywhere +else. """ + +from Bcfg2.Compat import any # pylint: disable=W0622 + + +class PackedDigitRange(object): + """ Representation of a set of integer ranges. A range is + described by a comma-delimited string of integers and ranges, + e.g.:: + + 1,10-12,15-20 + + Ranges are inclusive on both bounds, and may include 0. Negative + numbers are not supported.""" + + def __init__(self, *ranges): + """ May be instantiated in one of two ways:: + + PackedDigitRange(<comma-delimited list of ranges>) + + Or:: + + PackedDigitRange(<int_or_range>[, <int_or_range>[, ...]]) + + E.g., both of the following are valid:: + + PackedDigitRange("1-5,7, 10-12") + PackedDigitRange("1-5", 7, "10-12") + """ + self.ranges = [] + self.ints = [] + self.str = ",".join(str(r) for r in ranges) + if len(ranges) == 1 and "," in ranges[0]: + ranges = ranges[0].split(",") + for item in ranges: + item = str(item).strip() + if item.endswith("-"): + self.ranges.append((int(item[:-1]), None)) + elif '-' in str(item): + self.ranges.append(tuple(int(x) for x in item.split('-'))) + else: + self.ints.append(int(item)) + + def includes(self, other): + """ Return True if ``other`` is included in this range. + Functionally equivalent to ``other in range``, which should be + used instead. """ + return other in self + + def __contains__(self, other): + other = int(other) + if other in self.ints: + return True + return any((end is None and other >= start) or + (end is not None and other >= start and other <= end) + for start, end in self.ranges) + + def __repr__(self): + return "%s:%s" % (self.__class__.__name__, str(self)) + + def __str__(self): + return "[%s]" % self.str + + def __len__(self): + return sum(r[1] - r[0] + 1 for r in self.ranges) + len(self.ints) |