Skip to content

Commit 79a08c8

Browse files
author
Anselm Kruis
committed
Stackless issue python#78: documentation update for iterating over channels
- document, that the sender must notify the receiver of an end-of-iteration condition by sending a StopIteration exception. - document the return value of channel.send_sequence() - issue python#53: document the behaviour of channel.close() - add another test case to test_chanel. https://bitbucket.org/stackless-dev/stackless/issues/78 https://bitbucket.org/stackless-dev/stackless/issues/53 (grafted from 38b6cdef017849134ee433c78d6daf168c1c01e2)
1 parent 587fa64 commit 79a08c8

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

Doc/library/stackless/channels.rst

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,20 @@ The ``channel`` class
102102
.. method:: channel.send_sequence(seq)
103103

104104
Send a stream of values over the channel. Combined with a generator, this
105-
is a very efficient way to build fast pipes.
105+
is a very efficient way to build fast pipes. This method returns the length
106+
of *seq*.
107+
108+
This method is equivalent to::
109+
110+
def send_sequence(channel, sequence):
111+
length = 0
112+
for item in sequence:
113+
channel.send(item)
114+
length += 1
115+
return length
106116

107117
Example - sending a sequence over a channel::
108-
118+
109119
>>> def sender(channel):
110120
... channel.send_sequence(sequence)
111121
...
@@ -135,11 +145,23 @@ The ``channel`` class
135145
Channels can work as an iterator. When they are used in this way, call
136146
overhead is removed on the receiving side, making it an efficient approach.
137147

148+
The receiver does not know, if the sender will send further objects
149+
or not. Therefore the sender must notify the receiver about the
150+
end-of-iteration condition. Currently this requires sending a
151+
:exc:`StopIteration` over the channel (i.e. by
152+
calling ``channel.send_exception(StopIteration)``).
153+
154+
.. note::
155+
156+
A future version of Stackless may send a :exc:`StopIteration` automatically,
157+
if you close the channel.
158+
138159
Example - iterating over a channel::
139160
140161
>>> def sender(channel):
141162
... for value in sequence:
142163
... channel.send(value)
164+
... channel.send_exception(StopIteration)
143165
...
144166
>>> def receiver(channel):
145167
... for value in channel:
@@ -159,6 +181,27 @@ The ``channel`` class
159181
2
160182
3
161183

184+
Of course you can combine :meth:`send_sequence` with iterating over a channel::
185+
186+
>>> def sender(channel, sequence):
187+
... channel.send_sequence(sequence)
188+
... channel.send_exception(StopIteration)
189+
...
190+
>>> def receiver(channel):
191+
... for value in channel:
192+
... print value
193+
...
194+
>>> c = stackless.channel()
195+
>>> stackless.tasklet(sender)(c, range(4))
196+
<_stackless.tasklet object at 0x0244E0E8>
197+
>>> stackless.tasklet(receiver)(c)
198+
<_stackless.tasklet object at 0x0244E140>
199+
>>> stackless.run()
200+
0
201+
1
202+
2
203+
3
204+
162205
.. method:: channel.next()
163206

164207
Part of the :ref:`iteration protocol <typeiter>`. Either returns the next value, or raises

Stackless/changelog.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ What's New in Stackless 3.X.X?
1010

1111
*Release date: 20XX-XX-XX*
1212

13+
- https://bitbucket.org/stackless-dev/stackless/issues/78
14+
Documentation update: if you iterate over a channel, the
15+
sender must send StopIteration manually. See
16+
http://stackless.readthedocs.io/en/latest/library/stackless/channels.html#channel.__iter__
17+
1318
- https://bitbucket.org/stackless-dev/stackless/issue/83
1419
Fix demo/tracing.py: don't use flextype features. Unfortunately
1520
it is no longer possible to change the __repr__ method of class tasklet.

Stackless/unittests/test_channel.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ def setUp(self):
240240
self.c = stackless.channel()
241241

242242
# TODO: This test shows how ill conceived the current closing/closed semantics are.
243+
# See https://bitbucket.org/stackless-dev/stackless/issues/53
243244
def testSequence(self):
244245
def sender():
245246
self.c.send_sequence(range(10))
@@ -264,6 +265,28 @@ def receiver():
264265
self.assertEqual(data, list(range(11)))
265266
self.assertTrue(self.c.closed)
266267

268+
def testSequence2(self):
269+
def sender():
270+
length = self.c.send_sequence(range(10))
271+
self.assertEqual(length, 10)
272+
# A future version of Stackless may send StopIteration
273+
# automatically, if you close the channel
274+
# See https://bitbucket.org/stackless-dev/stackless/issues/53
275+
self.c.send_exception(StopIteration)
276+
self.c.close()
277+
278+
data = []
279+
280+
def receiver():
281+
for i in self.c:
282+
data.append(i)
283+
284+
stackless.tasklet(sender)()
285+
stackless.tasklet(receiver)()
286+
stackless.run()
287+
self.assertEqual(data, list(range(10)))
288+
self.assertTrue(self.c.closed)
289+
267290
def testSender(self):
268291
self.c.close()
269292
self.assertRaises(ValueError, self.c.send, None)

0 commit comments

Comments
 (0)