1.1 --- a/vRecurrence.py Sun Dec 03 21:59:54 2017 +0100
1.2 +++ b/vRecurrence.py Sun Dec 03 22:45:22 2017 +0100
1.3 @@ -534,6 +534,10 @@
1.4
1.5 # Add the qualifier to the combined list.
1.6
1.7 + if isinstance(from_sel, Pattern):
1.8 + if not have_sel:
1.9 + have_sel = from_sel.first = True
1.10 +
1.11 l.append(from_sel)
1.12
1.13 # Datetime value at same resolution.
1.14 @@ -565,17 +569,16 @@
1.15 Take the selector 'from_sel' at the given resolution 'level', using it to
1.16 create an initial selector, adding it to the combined list 'l' if required.
1.17
1.18 - Return whether a frequency selector has been introduced or if 'from_sel' is
1.19 - such a selector.
1.20 + Return whether a frequency selector has been introduced.
1.21 """
1.22
1.23 if isinstance(from_sel, Enum) and level > 0:
1.24 parent_level = enum_parent_levels[level]
1.25 - repeat = Pattern(parent_level, {"interval" : 1}, freq_levels[parent_level])
1.26 + repeat = Pattern(parent_level, {"interval" : 1}, freq_levels[parent_level], first=True)
1.27 l.append(repeat)
1.28 return True
1.29
1.30 - return isinstance(from_sel, Pattern)
1.31 + return False
1.32
1.33 def add_datetime_selector(from_dt, l):
1.34
1.35 @@ -871,7 +874,7 @@
1.36
1.37 "A generic selector."
1.38
1.39 - def __init__(self, level, args, qualifier, selecting=None, first=False):
1.40 + def __init__(self, level, args, qualifier, selecting=None):
1.41
1.42 """
1.43 Initialise at the given 'level' a selector employing the given 'args'
1.44 @@ -885,12 +888,11 @@
1.45 self.args = args or {}
1.46 self.qualifier = qualifier
1.47 self.selecting = selecting
1.48 - self.first = first
1.49
1.50 def __repr__(self):
1.51 - return "%s(%s, %r, %r, %r)" % (self.__class__.__name__,
1.52 - level_labels[self.level],
1.53 - self.args, self.qualifier, self.first)
1.54 + return "%s(%s, %r, %r)" % (self.__class__.__name__,
1.55 + level_labels[self.level],
1.56 + self.args, self.qualifier)
1.57
1.58 def select(self, start, end, inclusive=False):
1.59
1.60 @@ -926,8 +928,9 @@
1.61 "A selector of time periods according to a repeating pattern."
1.62
1.63 def __init__(self, level, args, qualifier, selecting=None, first=False):
1.64 - Selector.__init__(self, level, args, qualifier, selecting, first)
1.65 + Selector.__init__(self, level, args, qualifier, selecting)
1.66 multiple = get_multiple(self.qualifier)
1.67 + self.first = first
1.68
1.69 # Define the scale of a single period.
1.70
1.71 @@ -977,8 +980,8 @@
1.72
1.73 "A generic value selector."
1.74
1.75 - def __init__(self, level, args, qualifier, selecting=None, first=False):
1.76 - Selector.__init__(self, level, args, qualifier, selecting, first)
1.77 + def __init__(self, level, args, qualifier, selecting=None):
1.78 + Selector.__init__(self, level, args, qualifier, selecting)
1.79 self.step = scale(1, level)
1.80
1.81 def materialise_items(self, context, start, end, inclusive=False):
1.82 @@ -992,8 +995,8 @@
1.83
1.84 "A selector of instances specified in terms of day numbers."
1.85
1.86 - def __init__(self, level, args, qualifier, selecting=None, first=False):
1.87 - Selector.__init__(self, level, args, qualifier, selecting, first)
1.88 + def __init__(self, level, args, qualifier, selecting=None):
1.89 + Selector.__init__(self, level, args, qualifier, selecting)
1.90 self.step = scale(1, WEEKS)
1.91
1.92 def materialise_items(self, context, start, end, inclusive=False):
1.93 @@ -1076,8 +1079,8 @@
1.94
1.95 "A result set position selector."
1.96
1.97 - def __init__(self, level, args, qualifier, selecting=None, first=False):
1.98 - Selector.__init__(self, level, args, qualifier, selecting, first)
1.99 + def __init__(self, level, args, qualifier, selecting=None):
1.100 + Selector.__init__(self, level, args, qualifier, selecting)
1.101 if level is not None:
1.102 self.set_level(level)
1.103 else:
1.104 @@ -1181,9 +1184,13 @@
1.105
1.106 def at_limit(self):
1.107
1.108 - "Obtain periods before the end (and also at the end if inclusive)."
1.109 + """
1.110 + Obtain periods before the end. If inclusive and selecting in the final
1.111 + selector, obtain the period at the end.
1.112 + """
1.113
1.114 - return not self.inclusive and self.current == self.end or \
1.115 + inclusive = self.inclusive and not self.selector.selecting
1.116 + return not inclusive and self.current == self.end or \
1.117 self.current > self.end
1.118
1.119 class PatternIterator(SelectorIterator):
1.120 @@ -1462,40 +1469,36 @@
1.121
1.122 "Return the next value, initially the start period."
1.123
1.124 - while not self.at_limit():
1.125 -
1.126 - # Obtain the next item.
1.127 -
1.128 - try:
1.129 - result = self.next_item(self.start, self.end)
1.130 - except StopIteration:
1.131 + # Obtain the next item.
1.132
1.133 - # With no more values, flush any waiting value.
1.134 + try:
1.135 + result = self.next_item(self.start, self.end)
1.136 + except StopIteration:
1.137
1.138 - if self.waiting is not None:
1.139 - result = self.waiting
1.140 - self.waiting = None
1.141 - return result
1.142 - else:
1.143 - raise
1.144 -
1.145 - # Compare with any waiting value.
1.146 + # With no more values, flush any waiting value.
1.147
1.148 if self.waiting is not None:
1.149 -
1.150 - # Produce the waiting value, queue the latest result.
1.151 + result = self.waiting
1.152 + self.waiting = None
1.153 + return result
1.154 + else:
1.155 + raise
1.156
1.157 - if result != self.waiting:
1.158 - result, self.waiting = self.waiting, result
1.159 + # Compare with any waiting value.
1.160 +
1.161 + if self.waiting is not None:
1.162
1.163 - # Remove the waiting value if identical to the latest result.
1.164 + # Produce the waiting value, queue the latest result.
1.165 +
1.166 + if result != self.waiting:
1.167 + result, self.waiting = self.waiting, result
1.168
1.169 - else:
1.170 - self.waiting = None
1.171 + # Remove the waiting value if identical to the latest result.
1.172
1.173 - return result
1.174 + else:
1.175 + self.waiting = None
1.176
1.177 - raise StopIteration
1.178 + return result
1.179
1.180 def connect_selectors(selectors):
1.181
1.182 @@ -1506,18 +1509,10 @@
1.183 """
1.184
1.185 current = selectors[0]
1.186 - current.first = first = True
1.187
1.188 for selector in selectors[1:]:
1.189 current.selecting = selector
1.190 -
1.191 - # Allow selectors within the limit selector to act as if they are first
1.192 - # in the chain and will operate using the supplied datetime context.
1.193 -
1.194 - first = isinstance(current, (LimitSelector, StartSelector))
1.195 -
1.196 current = selector
1.197 - current.first = first
1.198
1.199 return selectors[0]
1.200