1.1 --- a/vRecurrence.py Sat Feb 28 22:30:52 2015 +0100
1.2 +++ b/vRecurrence.py Sun Mar 01 00:20:17 2015 +0100
1.3 @@ -405,23 +405,26 @@
1.4 def __repr__(self):
1.5 return "%s(%r, %r, %r, %r)" % (self.__class__.__name__, self.level, self.args, self.qualifier, self.context)
1.6
1.7 - def materialise(self, start, end, count=None, setpos=None):
1.8 + def materialise(self, start, end, count=None, setpos=None, inclusive=False):
1.9
1.10 """
1.11 Starting at 'start', materialise instances up to but not including any
1.12 at 'end' or later, returning at most 'count' if specified, and returning
1.13 only the occurrences indicated by 'setpos' if specified. A list of
1.14 instances is returned.
1.15 +
1.16 + If 'inclusive' is specified, the selection of instances will include the
1.17 + end of the search period if present in the results.
1.18 """
1.19
1.20 start = to_tuple(start)
1.21 end = to_tuple(end)
1.22 counter = count and [0, count]
1.23 - results = self.materialise_items(self.context, start, end, counter, setpos)
1.24 + results = self.materialise_items(self.context, start, end, counter, setpos, inclusive)
1.25 results.sort()
1.26 return results[:count]
1.27
1.28 - def materialise_item(self, current, earliest, next, counter, setpos=None):
1.29 + def materialise_item(self, current, earliest, next, counter, setpos=None, inclusive=False):
1.30
1.31 """
1.32 Given the 'current' instance, the 'earliest' acceptable instance, the
1.33 @@ -432,7 +435,7 @@
1.34 """
1.35
1.36 if self.selecting:
1.37 - return self.selecting.materialise_items(current, earliest, next, counter, setpos)
1.38 + return self.selecting.materialise_items(current, earliest, next, counter, setpos, inclusive)
1.39 elif earliest <= current:
1.40 return [current]
1.41 else:
1.42 @@ -459,16 +462,19 @@
1.43 l += results[lower:upper]
1.44 return l
1.45
1.46 - def filter_by_period(self, results, start, end):
1.47 + def filter_by_period(self, results, start, end, inclusive):
1.48
1.49 """
1.50 Filter 'results' so that only those at or after 'start' and before 'end'
1.51 are returned.
1.52 +
1.53 + If 'inclusive' is specified, the selection of instances will include the
1.54 + end of the search period if present in the results.
1.55 """
1.56
1.57 l = []
1.58 for result in results:
1.59 - if start <= result < end:
1.60 + if start <= result and (inclusive and result <= end or result < end):
1.61 l.append(result)
1.62 return l
1.63
1.64 @@ -476,7 +482,7 @@
1.65
1.66 "A selector of instances according to a repeating pattern."
1.67
1.68 - def materialise_items(self, context, start, end, counter, setpos=None):
1.69 + def materialise_items(self, context, start, end, counter, setpos=None, inclusive=False):
1.70 first = scale(self.context[self.pos], self.pos)
1.71
1.72 # Define the step between items.
1.73 @@ -492,10 +498,10 @@
1.74 current = combine(context, first)
1.75 results = []
1.76
1.77 - while current < end and (counter is None or counter[0] < counter[1]):
1.78 + while (inclusive and current <= end or current < end) and (counter is None or counter[0] < counter[1]):
1.79 next = update(current, step)
1.80 current_end = update(current, unit_step)
1.81 - interval_results = self.materialise_item(current, max(current, start), min(current_end, end), counter, setpos)
1.82 + interval_results = self.materialise_item(current, max(current, start), min(current_end, end), counter, setpos, inclusive)
1.83 if counter is not None:
1.84 counter[0] += len(interval_results)
1.85 results += interval_results
1.86 @@ -507,7 +513,7 @@
1.87
1.88 "A selector of instances specified in terms of day numbers."
1.89
1.90 - def materialise_items(self, context, start, end, counter, setpos=None):
1.91 + def materialise_items(self, context, start, end, counter, setpos=None, inclusive=False):
1.92 step = scale(1, 2)
1.93 results = []
1.94
1.95 @@ -530,10 +536,10 @@
1.96 current = context
1.97 values = [value for (value, index) in self.args["values"]]
1.98
1.99 - while current < end:
1.100 + while (inclusive and current <= end or current < end):
1.101 next = update(current, step)
1.102 if date(*current).isoweekday() in values:
1.103 - results += self.materialise_item(current, max(current, start), min(next, end), counter)
1.104 + results += self.materialise_item(current, max(current, start), min(next, end), counter, inclusive=inclusive)
1.105 current = next
1.106
1.107 if setpos:
1.108 @@ -557,7 +563,7 @@
1.109 # To support setpos, only current and next bound the search, not
1.110 # the period in addition.
1.111
1.112 - results += self.materialise_item(current, current, next, counter)
1.113 + results += self.materialise_item(current, current, next, counter, inclusive=inclusive)
1.114
1.115 else:
1.116 if index < 0:
1.117 @@ -573,7 +579,7 @@
1.118 # To support setpos, only current and next bound the search, not
1.119 # the period in addition.
1.120
1.121 - results += self.materialise_item(current, current, next, counter)
1.122 + results += self.materialise_item(current, current, next, counter, inclusive=inclusive)
1.123 current = to_tuple(direction(date(*current), timedelta(7)), 3)
1.124
1.125 # Extract selected positions and remove out-of-period instances.
1.126 @@ -581,10 +587,10 @@
1.127 if setpos:
1.128 results = self.select_positions(results, setpos)
1.129
1.130 - return self.filter_by_period(results, start, end)
1.131 + return self.filter_by_period(results, start, end, inclusive)
1.132
1.133 class Enum(Selector):
1.134 - def materialise_items(self, context, start, end, counter, setpos=None):
1.135 + def materialise_items(self, context, start, end, counter, setpos=None, inclusive=False):
1.136 step = scale(1, self.pos)
1.137 results = []
1.138 for value in self.args["values"]:
1.139 @@ -594,17 +600,17 @@
1.140 # To support setpos, only current and next bound the search, not
1.141 # the period in addition.
1.142
1.143 - results += self.materialise_item(current, current, next, counter, setpos)
1.144 + results += self.materialise_item(current, current, next, counter, setpos, inclusive)
1.145
1.146 # Extract selected positions and remove out-of-period instances.
1.147
1.148 if setpos:
1.149 results = self.select_positions(results, setpos)
1.150
1.151 - return self.filter_by_period(results, start, end)
1.152 + return self.filter_by_period(results, start, end, inclusive)
1.153
1.154 class MonthDayFilter(Enum):
1.155 - def materialise_items(self, context, start, end, counter, setpos=None):
1.156 + def materialise_items(self, context, start, end, counter, setpos=None, inclusive=False):
1.157 last_day = monthrange(context[0], context[1])[1]
1.158 step = scale(1, self.pos)
1.159 results = []
1.160 @@ -617,17 +623,17 @@
1.161 # To support setpos, only current and next bound the search, not
1.162 # the period in addition.
1.163
1.164 - results += self.materialise_item(current, current, next, counter)
1.165 + results += self.materialise_item(current, current, next, counter, inclusive=inclusive)
1.166
1.167 # Extract selected positions and remove out-of-period instances.
1.168
1.169 if setpos:
1.170 results = self.select_positions(results, setpos)
1.171
1.172 - return self.filter_by_period(results, start, end)
1.173 + return self.filter_by_period(results, start, end, inclusive)
1.174
1.175 class YearDayFilter(Enum):
1.176 - def materialise_items(self, context, start, end, counter, setpos=None):
1.177 + def materialise_items(self, context, start, end, counter, setpos=None, inclusive=False):
1.178 first_day = date(context[0], 1, 1)
1.179 next_first_day = date(context[0] + 1, 1, 1)
1.180 year_length = (next_first_day - first_day).days
1.181 @@ -642,14 +648,14 @@
1.182 # To support setpos, only current and next bound the search, not
1.183 # the period in addition.
1.184
1.185 - results += self.materialise_item(current, current, next, counter)
1.186 + results += self.materialise_item(current, current, next, counter, inclusive=inclusive)
1.187
1.188 # Extract selected positions and remove out-of-period instances.
1.189
1.190 if setpos:
1.191 results = self.select_positions(results, setpos)
1.192
1.193 - return self.filter_by_period(results, start, end)
1.194 + return self.filter_by_period(results, start, end, inclusive)
1.195
1.196 special_enum_levels = {
1.197 "BYDAY" : WeekDayFilter,