22
22
from contextlib import (
23
23
asynccontextmanager as acm ,
24
24
contextmanager as cm ,
25
- nullcontext ,
26
25
)
27
26
from typing import (
28
27
Generator ,
@@ -51,7 +50,7 @@ class TaskOutcome(Struct):
51
50
52
51
'''
53
52
lowlevel_task : Task
54
- _exited : Event = trio .Event () # as per `trio.Runner.task_exited()`
53
+ _exited = trio .Event () # as per `trio.Runner.task_exited()`
55
54
_outcome : Outcome | None = None # as per `outcome.Outcome`
56
55
_result : Any | None = None # the eventual maybe-returned-value
57
56
@@ -63,9 +62,8 @@ def result(self) -> Any:
63
62
'''
64
63
if self ._outcome is None :
65
64
raise RuntimeError (
66
- # f'Task {task.name} is not complete.\n'
67
- f'Outcome is not complete.\n '
68
- 'wait on `await TaskOutcome.wait_for_result()` first!'
65
+ f'Task { self .lowlevel_task .name } is not complete.\n '
66
+ 'First wait on `await TaskOutcome.wait_for_result()`!'
69
67
)
70
68
return self ._result
71
69
@@ -102,22 +100,22 @@ async def wait_for_result(self) -> Any:
102
100
return self .result
103
101
104
102
105
- class ScopePerTaskNursery (Struct ):
103
+ class TaskManagerNursery (Struct ):
106
104
_n : Nursery
107
105
_scopes : dict [
108
106
Task ,
109
107
tuple [CancelScope , Outcome ]
110
108
] = {}
111
109
112
- scope_manager : Generator [Any , Outcome , None ] | None = None
110
+ task_manager : Generator [Any , Outcome , None ] | None = None
113
111
114
112
async def start_soon (
115
113
self ,
116
114
async_fn ,
117
115
* args ,
118
116
119
117
name = None ,
120
- scope_manager : ContextManager | None = None ,
118
+ task_manager : Generator [ Any , Outcome , None ] | None = None
121
119
122
120
) -> tuple [CancelScope , Task ]:
123
121
@@ -131,7 +129,7 @@ async def start_soon(
131
129
132
130
n : Nursery = self ._n
133
131
134
- sm = self .scope_manager
132
+ sm = self .task_manager
135
133
# we do default behavior of a scope-per-nursery
136
134
# if the user did not provide a task manager.
137
135
if sm is None :
@@ -151,7 +149,8 @@ async def _start_wrapped_in_scope(
151
149
152
150
) -> None :
153
151
154
- # TODO: this was working before?!
152
+ # TODO: this was working before?! and, do we need something
153
+ # like it to implement `.start()`?
155
154
# nonlocal to_return
156
155
157
156
# execute up to the first yield
@@ -203,15 +202,10 @@ async def _start_wrapped_in_scope(
203
202
# TODO: define a decorator to runtime type check that this a generator
204
203
# with a single yield that also delivers a value (of some std type) from
205
204
# the yield expression?
206
- # @trio.task_scope_manager
205
+ # @trio.task_manager
207
206
def add_task_handle_and_crash_handling (
208
207
nursery : Nursery ,
209
208
210
- # TODO: is this the only way we can have a per-task scope
211
- # allocated or can we allow the user to somehow do it if
212
- # they want below?
213
- # scope: CancelScope,
214
-
215
209
) -> Generator [
216
210
Any ,
217
211
Outcome ,
@@ -261,14 +255,11 @@ def add_task_handle_and_crash_handling(
261
255
262
256
@acm
263
257
async def open_nursery (
264
- scope_manager = None ,
258
+ task_manager = None ,
265
259
** kwargs ,
266
260
):
267
261
async with trio .open_nursery (** kwargs ) as nurse :
268
- yield ScopePerTaskNursery (
269
- nurse ,
270
- scope_manager = scope_manager ,
271
- )
262
+ yield TaskManagerNursery (nurse , task_manager = task_manager )
272
263
273
264
274
265
async def sleep_then_return_val (val : str ):
@@ -293,7 +284,7 @@ async def ensure_cancelled():
293
284
294
285
async def main ():
295
286
async with open_nursery (
296
- scope_manager = add_task_handle_and_crash_handling ,
287
+ task_manager = add_task_handle_and_crash_handling ,
297
288
) as sn :
298
289
for _ in range (3 ):
299
290
outcome , _ = await sn .start_soon (trio .sleep_forever )
@@ -312,7 +303,7 @@ async def main():
312
303
313
304
await trio .sleep (0.6 )
314
305
print (
315
- 'Cancelling and waiting on {err_outcome.lowlevel_task} '
306
+ f 'Cancelling and waiting on { err_outcome .lowlevel_task } '
316
307
'to CRASH..'
317
308
)
318
309
cs .cancel ()
0 commit comments