@@ -112,6 +112,76 @@ class Task
112
112
ignore this exception. Cleanup code may be run by trapping it, or via
113
113
``try ... finally ``.
114
114
115
+ class Taskgroup
116
+ ---------------
117
+
118
+ See Nathaniel J. Smith's `essay on Structured Concurrency
119
+ <https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/> `_
120
+ for an introduction why you should use taskgroups instead of starting
121
+ "naked" tasks.
122
+
123
+ .. note ::
124
+ His "nursery" objects are called "taskgroup" in asyncio; the
125
+ equivalent of a "go statement" is `Loop.create_task `.
126
+
127
+ .. class :: Taskgroup()
128
+
129
+ This object is an async context managed holding a group of tasks.
130
+ Tasks can be added to the group using `Taskgroup.create_task `.
131
+
132
+ If a task belonging to the group fails, the remaining tasks in the
133
+ group are cancelled with an :exc: `asyncio.CancelledError ` exception.
134
+ (This also holds for the code within the context manager's block.)
135
+ No further tasks can then be added to the group.
136
+
137
+ When there is no exception, leaving the context manager waits for
138
+ the taskgroup's member tasks to end before proceeding. It does not
139
+ cancel these tasks and does not prevent the creation of new tasks.
140
+
141
+ .. method :: Taskgroup.create_task(coroutine)
142
+
143
+ Create a subtask that executes *coroutine * as part of this taskgroup.
144
+
145
+ Returns the new task.
146
+
147
+ .. method :: Taskgroup.cancel()
148
+
149
+ Stop the taskgroup, i.e. cancel all its tasks.
150
+
151
+ This method is equivalent to cancelling the task responsible for the
152
+ body of the taskgroup, *if * that is what the task is currently doing.
153
+
154
+ .. exception :: Cancelled
155
+
156
+ This exception is raised in a task whose taskgroup is being cancelled.
157
+
158
+ This is a subclass of ``BaseException ``; it should never be caught.
159
+
160
+ .. exception :: ExceptionGroup
161
+
162
+ If multiple subtasks raise exceptions in parallel, it's unclear which
163
+ of them should be propagated. Thus an `ExceptionGroup ` exception
164
+ collects them and is raised instead.
165
+
166
+ .. method :: ExceptionGroup.split(typ)
167
+
168
+ This method can be used to filter the exceptions within an exception group.
169
+ It returns two lists: the first contains those sub-exceptions which
170
+ match *typ *, the second those which do not.
171
+
172
+ *typ * can be an exception class, a list of exception classes, or a
173
+ callable that returns ``True `` if the exception passed to it should be
174
+ returned in the first list.
175
+
176
+ MicroPython does not support CPython 3.11's syntax for filtering handling
177
+ exception groups.
178
+
179
+ .. exception :: BaseExceptionGroup
180
+
181
+ Like `ExceptionGroup `, but used if one of the sub-exceptions is not a
182
+ subclass of `Exception `.
183
+
184
+
115
185
class Event
116
186
-----------
117
187
@@ -214,20 +284,37 @@ TCP stream connections
214
284
215
285
.. function :: start_server(callback, host, port, backlog=5)
216
286
217
- Start a TCP server on the given *host * and *port *. The *callback * will be
218
- called with incoming, accepted connections, and be passed 2 arguments: reader
219
- and writer streams for the connection.
287
+ Start a TCP server on the given *host * and *port *. For each incoming,
288
+ accepted connection, *callback * will be called in a new task with
289
+ 2 arguments: reader and writer streams for the connection.
290
+
291
+ If you use taskgroups, you should use `run_server ` instead.
220
292
221
293
Returns a `Server ` object.
222
294
223
295
This is a coroutine.
224
296
297
+ .. function :: run_server(callback, host, port, backlog=5, taskgroup=None)
298
+
299
+ Start a TCP server on the given *host * and *port *. For each incoming,
300
+ accepted connection, *callback * will be called in a new task with
301
+ 2 arguments: reader and writer streams for the connection.
302
+
303
+ The new task is started in *taskgroup *. An internal taskgroup will be
304
+ used if none is passed in.
305
+
306
+ This is a coroutine. It does not return unless cancelled.
307
+
308
+
225
309
.. class :: Stream()
226
310
227
311
This represents a TCP stream connection. To minimise code this class implements
228
312
both a reader and a writer, and both ``StreamReader `` and ``StreamWriter `` alias to
229
313
this class.
230
314
315
+ This class should be used as an async context manager. Leaving the context
316
+ will close the connection.
317
+
231
318
.. method :: Stream.get_extra_info(v)
232
319
233
320
Get extra information about the stream, given by *v *. The valid values for *v * are:
@@ -237,6 +324,12 @@ TCP stream connections
237
324
238
325
Close the stream.
239
326
327
+ Depending on the stream's concrete implementation, this call may do
328
+ nothing. You should call the `wait_closed ` coroutine immediately
329
+ afterwards.
330
+
331
+ Streams are closed implicitly when used as an async context manager.
332
+
240
333
.. method :: Stream.wait_closed()
241
334
242
335
Wait for the stream to close.
@@ -323,6 +416,8 @@ Event Loop
323
416
324
417
Create a task from the given *coro * and return the new `Task ` object.
325
418
419
+ You should not call this function when you're using taskgroups.
420
+
326
421
.. method :: Loop.run_forever()
327
422
328
423
Run the event loop until `stop() ` is called.
0 commit comments