1515# along with this program. If not, see <https://www.gnu.org/licenses/>.
1616
1717'''
18- Erlang-style (ish) "one-cancels-one" nursery.
18+ Erlang-style (ish) "one-cancels-one" nursery, what we just call
19+ a "task manager".
1920
2021'''
2122from __future__ import annotations
2223from contextlib import (
2324 asynccontextmanager as acm ,
24- contextmanager as cm ,
25+ # contextmanager as cm,
2526)
2627from functools import partial
2728from typing import (
3536)
3637from msgspec import Struct
3738import trio
38- from trio . _core . _run import (
39- Task ,
39+ from trio import (
40+ TaskStatus ,
4041 CancelScope ,
4142 Nursery ,
4243)
44+ from trio .lowlevel import (
45+ Task ,
46+ )
47+ from tractor .log import get_logger
48+
49+ log = get_logger (__name__ )
4350
4451
4552class TaskOutcome (Struct ):
@@ -101,7 +108,7 @@ async def wait_for_result(self) -> Any:
101108
102109
103110class TaskManagerNursery (Struct ):
104- _n : Nursery
111+ _tn : Nursery
105112 _scopes : dict [
106113 Task ,
107114 tuple [CancelScope , Outcome ]
@@ -127,20 +134,20 @@ async def start_soon(
127134 # assert len(new_tasks) == 1
128135 # task = new_tasks.pop()
129136
130- n : Nursery = self ._n
137+ tn : Nursery = self ._tn
131138
132139 sm = self .task_manager
133140 # we do default behavior of a scope-per-nursery
134141 # if the user did not provide a task manager.
135142 if sm is None :
136- return n .start_soon (async_fn , * args , name = None )
143+ return tn .start_soon (async_fn , * args , name = None )
137144
138- new_task : Task | None = None
145+ # new_task: Task| None = None
139146 to_return : tuple [Any ] | None = None
140147
141148 # NOTE: what do we enforce as a signature for the
142149 # `@task_scope_manager` here?
143- mngr = sm (nursery = n )
150+ mngr = sm (nursery = tn )
144151
145152 async def _start_wrapped_in_scope (
146153 task_status : TaskStatus [
@@ -190,7 +197,7 @@ async def _start_wrapped_in_scope(
190197 else :
191198 raise RuntimeError (f"{ mngr } didn't stop!" )
192199
193- to_return = await n .start (_start_wrapped_in_scope )
200+ to_return = await tn .start (_start_wrapped_in_scope )
194201 assert to_return is not None
195202
196203 # TODO: use the fancy type-check-time type signature stuff from
@@ -222,7 +229,7 @@ def add_task_handle_and_crash_handling(
222229 '''
223230 # if you need it you can ask trio for the task obj
224231 task : Task = trio .lowlevel .current_task ()
225- print (f'Spawning task: { task .name } ' )
232+ log . info (f'Spawning task: { task .name } ' )
226233
227234 # User defined "task handle" for more granular supervision
228235 # of each spawned task as needed for their particular usage.
@@ -247,18 +254,27 @@ def add_task_handle_and_crash_handling(
247254 # Adds "crash handling" from `pdbp` by entering
248255 # a REPL on std errors.
249256 except Exception as err :
250- print (f'{ task .name } crashed, entering debugger!' )
251257 if debug_mode :
258+ log .exception (
259+ f'{ task .name } crashed, entering debugger!'
260+ )
252261 import pdbp
253262 pdbp .xpm ()
254- raise
263+
264+ raise err
255265
256266 finally :
257- print (f'{ task .name } Exitted' )
267+ log .info (
268+ f'Task exitted\n '
269+ f')>\n '
270+ f' |_{ task } \n '
271+ # ^^TODO? use sclang formatter?
272+ # -[ ] .devx.pformat.nest_from_op()` yo!
273+ )
258274
259275
260276@acm
261- async def open_nursery (
277+ async def open_taskman (
262278 task_manager : Generator [Any , Outcome , None ] | None = None ,
263279
264280 ** lowlevel_nursery_kwargs ,
@@ -281,7 +297,7 @@ async def ensure_cancelled():
281297
282298 except trio .Cancelled :
283299 task = trio .lowlevel .current_task ()
284- print (f'heyyo ONLY { task .name } was cancelled as expected B)' )
300+ log . cancel (f'heyyo ONLY { task .name } was cancelled as expected B)' )
285301 assert 0
286302
287303 except BaseException :
@@ -290,30 +306,33 @@ async def ensure_cancelled():
290306
291307if __name__ == '__main__' :
292308
309+ from tractor .log import get_console_log
310+ get_console_log (level = 'info' )
311+
293312 async def main ():
294- async with open_nursery (
313+ async with open_taskman (
295314 task_manager = partial (
296315 add_task_handle_and_crash_handling ,
297316 debug_mode = True ,
298317 ),
299- ) as sn :
318+ ) as tm :
300319 for _ in range (3 ):
301- outcome , _ = await sn .start_soon (trio .sleep_forever )
320+ outcome , _ = await tm .start_soon (trio .sleep_forever )
302321
303322 # extra task we want to engage in debugger post mortem.
304- err_outcome , cs = await sn .start_soon (ensure_cancelled )
323+ err_outcome , cs = await tm .start_soon (ensure_cancelled )
305324
306325 val : str = 'yoyoyo'
307- val_outcome , _ = await sn .start_soon (
326+ val_outcome , _ = await tm .start_soon (
308327 sleep_then_return_val ,
309328 val ,
310329 )
311330 res = await val_outcome .wait_for_result ()
312331 assert res == val
313- print (f'{ res } -> GOT EXPECTED TASK VALUE' )
332+ log . info (f'{ res } -> GOT EXPECTED TASK VALUE' )
314333
315334 await trio .sleep (0.6 )
316- print (
335+ log . cancel (
317336 f'Cancelling and waiting on { err_outcome .lowlevel_task } '
318337 'to CRASH..'
319338 )
0 commit comments