1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """C{window PREDICATE}
19
20 C{window -o WINDOW_SIZE}
21
22 C{window -d WINDOW_SIZE}
23
24 Groups of consecutive input objects are formed into tuples which are
25 passed to the output stream. The objects are grouped in one of two
26 mechanisms.
27
28 1) A new group is started on the first input object, and for any
29 subsequent object for which C{PREDICATE} returns true. For example, if
30 the input stream contains the integers C{1, 2, 3, ...}, then::
31
32 window 'n: n % 3 == 2'
33
34 yields as output::
35
36 ((1,),)
37 ((2,), (3,), (4,))
38 ((5,), (6,), (7,))
39 ((8,), (9,), (10,))
40 ...
41
42 I.e., a new tuple is started for each integer n such that n % 3 = 2.
43
44 2) Groups have a fixed number of objects. The C{-o} and C{-d} flags
45 specify C{WINDOW_SIZE}, the number of objects in the groups. C{-o}
46 specifies I{overlapping} windows, in which each input object begins a
47 new list containing C{WINDOW_SIZE} items. Groups may be padded with
48 C{None} values to ensure that the group's size is C{WINDOW_SIZE}.
49
50 B{Example}: For input C{0, 1, ..., 9}, C{window -o 3} yields these
51 tuples::
52
53 ((0,), (1,), (2,))
54 ((1,), (2,), (3,))
55 ((2,), (3,), (4,))
56 ((3,), (4,), (5,))
57 ((4,), (5,), (6,))
58 ((5,), (6,), (7,))
59 ((6,), (7,), (8,))
60 ((7,), (8,), (9,))
61 ((8,), (9,), (None,))
62 ((9,), (None,), (None,))
63
64 C{-d} specifies I{disjoint} windows, in which each input object
65 appears in only one group. A new group is started every C{WINDOW_SIZE}
66 objects. The last window may be padded with (None,) to ensure that it
67 has C{WINDOW_SIZE} elements.
68
69 B{Example}: For input C{0, 1, ..., 9}, C{window -d 3} yields these
70 tuples::
71
72 ((0,), (1,), (2,))
73 ((3,), (4,), (5,))
74 ((6,), (7,), (8,))
75 ((9,), (None,), (None,))
76 """
77
78 import types
79
80 import osh.args
81 import osh.core
82
83 Option = osh.args.Option
84
85
88
89
90 -def window(predicate = None, disjoint = None, overlap = None):
91 """Groups of consecutive input objects are formed into tuples which
92 are passed to the output stream. Only one of C{predicate},
93 C{disjoint}, ant C{overlap} may be specified. If C{predicate}, a
94 function returning a boolean, is specified, then a new group of
95 objects is started for the first input, and subsequently for every
96 input object which causes C{predicate} to return true. If
97 C{disjoint}, an integer, is specified, then the input is broken
98 into disjoint groups of C{disjoint} objects each. If C{overlap},
99 an int, is specified, then each input object begins a group of
100 C{overlap} objects. For both C{disjoint} and C{overlap}, groups
101 may be padded with C{None} values to form groups of the required
102 size.
103 """
104 arg = predicate
105 if not arg and disjoint:
106 arg = Option('-d', disjoint)
107 if not arg and overlap:
108 arg = Option('-o', overlap)
109 return _Window().process_args(arg)
110
112
113 _window_generator = None
114
115
116
117
120
121
122
123
126
128 args = self.args()
129 overlap = args.int_arg('-o')
130 disjoint = args.int_arg('-d')
131 if overlap is not None and disjoint is not None:
132 self.usage()
133 elif overlap is not None:
134 self._window_generator = _OverlapWindow(overlap)
135 elif disjoint is not None:
136 self._window_generator = _DisjointWindow(disjoint)
137 else:
138 predicate = args.next_function()
139 self._window_generator = _PredicateWindow(predicate)
140
142 self._window_generator.process(object, self)
143
145 self._window_generator.finish(self)
146 self.send_complete()
147
149
150 _window_size = None
151 _window = None
152
154 self._window_size = window_size
155 self._window = []
156
158 if len(self._window) == self._window_size:
159 self._window = self._window[1:]
160 self._window.append(object)
161 if len(self._window) == self._window_size:
162 op.send(self._window)
163
165 padding = (None,)
166 if len(self._window) < self._window_size:
167 while len(self._window) < self._window_size:
168 self._window.append(padding)
169 op.send(self._window)
170 else:
171 for i in xrange(self._window_size - 1):
172 self._window = self._window[1:]
173 self._window.append(padding)
174 op.send(self._window)
175
177
178 _window_size = None
179 _window = None
180
182 self._window_size = window_size
183 self._window = []
184
186 self._window.append(object)
187 if len(self._window) == self._window_size:
188 op.send(self._window)
189 self._window = []
190
192 if len(self._window) == 0:
193
194 pass
195 else:
196 padding = (None,)
197 while len(self._window) < self._window_size:
198 self._window.append(padding)
199 op.send(self._window)
200
202
203 _predicate = None
204 _window = None
205
207 self._predicate = predicate
208 self._window = []
209
211 if self._predicate(*object):
212 if len(self._window) > 0:
213 op.send(self._window)
214 self._window = []
215 self._window.append(object)
216
218 op.send(self._window)
219