@@ -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
@@ -215,22 +285,41 @@ TCP stream connections
215
285
216
286
.. function :: start_server(callback, host, port, backlog=5, ssl=None)
217
287
218
- Start a TCP server on the given *host * and *port *. The *callback * will be
219
- called with incoming, accepted connections, and be passed 2 arguments: reader
220
- and writer streams for the connection.
288
+ Start a TCP server on the given *host * and *port *. For each incoming,
289
+ accepted connection, *callback * will be called in a new task with
290
+ 2 arguments: reader and writer streams for the connection.
291
+
292
+ This function does **not ** co-operate well with taskgroups.
293
+ If you use them, you should use a function like `run_server `
294
+ (supplied in ``examples/run_server.py ``) instead.
221
295
222
296
If *ssl * is a `ssl.SSLContext ` object, this context is used to create the transport.
223
297
224
298
Returns a `Server ` object.
225
299
226
300
This is a coroutine.
227
301
302
+ .. function :: run_server(callback, host, port, backlog=5, taskgroup=None)
303
+
304
+ Start a TCP server on the given *host * and *port *. For each incoming,
305
+ accepted connection, *callback * will be called in a new task with
306
+ 2 arguments: reader and writer streams for the connection.
307
+
308
+ The new task is started in *taskgroup *. An internal taskgroup will be
309
+ used if none is passed in.
310
+
311
+ This is a coroutine. It does not return unless cancelled.
312
+
313
+
228
314
.. class :: Stream()
229
315
230
316
This represents a TCP stream connection. To minimise code this class implements
231
317
both a reader and a writer, and both ``StreamReader `` and ``StreamWriter `` alias to
232
318
this class.
233
319
320
+ This class should be used as an async context manager. Leaving the context
321
+ will close the connection.
322
+
234
323
.. method :: Stream.get_extra_info(v)
235
324
236
325
Get extra information about the stream, given by *v *. The valid values for *v * are:
@@ -240,6 +329,12 @@ TCP stream connections
240
329
241
330
Close the stream.
242
331
332
+ Depending on the stream's concrete implementation, this call may do
333
+ nothing. You should call the `wait_closed ` coroutine immediately
334
+ afterwards.
335
+
336
+ Streams are closed implicitly when used as an async context manager.
337
+
243
338
.. method :: Stream.wait_closed()
244
339
245
340
Wait for the stream to close.
@@ -326,6 +421,8 @@ Event Loop
326
421
327
422
Create a task from the given *coro * and return the new `Task ` object.
328
423
424
+ You should not call this function when you're using taskgroups.
425
+
329
426
.. method :: Loop.run_forever()
330
427
331
428
Run the event loop until `stop() ` is called.
0 commit comments