implement basic way to tell extractors to skip ahead

This commit is contained in:
Mike Fährmann
2017-03-03 17:26:50 +01:00
parent 872b8aed97
commit 7a9d66fbce
3 changed files with 48 additions and 13 deletions

View File

@@ -13,17 +13,14 @@ from . import exception
def parse_range(rangespec):
"""Parse an integer range and return the resulting ranges and upper limit
"""Parse an integer range string and return the resulting ranges
Examples
parse_range("-2,4,6-8,10-")
-> [(1,2), (4,4), (6,8), (10,INTMAX)], INTMAX
parse_range(" - 3 , 4- 4, 2-6")
-> [(1,3), (4,4), (2,6)], 6
parse_range("-2,4,6-8,10-") -> [(1,2), (4,4), (6,8), (10,INTMAX)]
parse_range(" - 3 , 4- 4, 2-6") -> [(1,3), (4,4), (2,6)]
"""
ranges = []
limit = 0
for group in rangespec.split(","):
parts = group.split("-", maxsplit=1)
try:
@@ -33,23 +30,52 @@ def parse_range(rangespec):
else:
beg = int(parts[0]) if parts[0].strip() else 1
end = int(parts[1]) if parts[1].strip() else sys.maxsize
ranges.append((beg, end))
limit = max(limit, end)
ranges.append((beg, end) if beg <= end else (end, beg))
except ValueError:
pass
return ranges, limit
return ranges
def optimize_range(ranges):
"""Simplify/Combine a parsed list of ranges
Examples
optimize_range([(2,4), (4,6), (5,8)]) -> [(2,8)]
optimize_range([(1,1), (2,2), (3,6), (8,9))]) -> [(1,6), (8-9)]
"""
if len(ranges) <= 1:
return ranges
ranges.sort()
riter = iter(ranges)
result = []
beg, end = next(riter)
for lower, upper in riter:
if lower > end+1:
result.append((beg, end))
beg, end = lower, upper
elif upper > end:
end = upper
result.append((beg, end))
return result
class RangePredicate():
"""Predicate; is True if the current index is in the given range"""
def __init__(self, rangespec):
self.ranges, self.limit = parse_range(rangespec)
self.ranges = optimize_range(parse_range(rangespec))
self.index = 0
if self.ranges:
self.lower, self.upper = self.ranges[0][0], self.ranges[-1][1]
else:
self.lower, self.upper = 0, 0
def __bool__(self):
self.index += 1
if self.index > self.limit:
if self.index > self.upper:
raise exception.StopExtraction()
for lower, upper in self.ranges: