Show More
@@ -42,49 +42,9 b' def _curio_runner(coroutine):' | |||
|
42 | 42 | return curio.run(coroutine) |
|
43 | 43 | |
|
44 | 44 | |
|
45 | _TRIO_TOKEN = None | |
|
46 | ||
|
47 | ||
|
48 | def _init_trio(trio): | |
|
49 | global _TRIO_TOKEN | |
|
50 | import traceback | |
|
51 | import builtins | |
|
52 | import threading | |
|
53 | # We use an Event to avoid a race condition between starting the Trio thread | |
|
54 | # and running Trio code. | |
|
55 | thread_start = threading.Event() | |
|
56 | ||
|
57 | def log_nursery_exc(exc): | |
|
58 | import logging | |
|
59 | import traceback | |
|
60 | exc = '\n'.join(traceback.format_exception(type(exc), exc, | |
|
61 | exc.__traceback__)) | |
|
62 | logging.error('An exception occurred in a global nursery task.\n%s', | |
|
63 | exc) | |
|
64 | ||
|
65 | async def trio_entry(): | |
|
66 | global _TRIO_TOKEN, _TRIO_NURSERY | |
|
67 | _TRIO_TOKEN = trio.hazmat.current_trio_token() | |
|
68 | async with trio.open_nursery() as nursery: | |
|
69 | # TODO This hack prevents the nursery from cancelling all child | |
|
70 | # tasks when but it's ugly. | |
|
71 | nursery._add_exc = log_nursery_exc | |
|
72 | builtins.GLOBAL_NURSERY = nursery | |
|
73 | thread_start.set() | |
|
74 | await trio.sleep_forever() | |
|
75 | ||
|
76 | threading.Thread(target=trio.run, args=(trio_entry,)).start() | |
|
77 | thread_start.wait() | |
|
78 | ||
|
79 | ||
|
80 | 45 | def _trio_runner(async_fn): |
|
81 | global _TRIO_TOKEN | |
|
82 | import logging | |
|
83 | 46 | import trio |
|
84 | 47 | |
|
85 | if not _TRIO_TOKEN: | |
|
86 | _init_trio(trio) | |
|
87 | ||
|
88 | 48 | async def loc(coro): |
|
89 | 49 | """ |
|
90 | 50 | We need the dummy no-op async def to protect from |
@@ -92,7 +52,7 b' def _trio_runner(async_fn):' | |||
|
92 | 52 | """ |
|
93 | 53 | return await coro |
|
94 | 54 | |
|
95 |
return trio |
|
|
55 | return trio.run(loc, async_fn) | |
|
96 | 56 | |
|
97 | 57 | |
|
98 | 58 | def _pseudo_sync_runner(coro): |
@@ -695,6 +695,13 b' class InteractiveShell(SingletonConfigurable):' | |||
|
695 | 695 | self.events.trigger('shell_initialized', self) |
|
696 | 696 | atexit.register(self.atexit_operations) |
|
697 | 697 | |
|
698 | # The trio runner is used for running Trio in the foreground thread. It | |
|
699 | # is different from `_trio_runner(async_fn)` in `async_helpers.py` | |
|
700 | # which calls `trio.run()` for every cell. This runner runs all cells | |
|
701 | # inside a single Trio event loop. If used, it is set from | |
|
702 | # `ipykernel.kernelapp`. | |
|
703 | self.trio_runner = None | |
|
704 | ||
|
698 | 705 | def get_ipython(self): |
|
699 | 706 | """Return the currently running IPython instance.""" |
|
700 | 707 | return self |
@@ -715,6 +722,9 b' class InteractiveShell(SingletonConfigurable):' | |||
|
715 | 722 | else: |
|
716 | 723 | self.autoindent = value |
|
717 | 724 | |
|
725 | def set_trio_runner(self, tr): | |
|
726 | self.trio_runner = tr | |
|
727 | ||
|
718 | 728 | #------------------------------------------------------------------------- |
|
719 | 729 | # init_* methods called by __init__ |
|
720 | 730 | #------------------------------------------------------------------------- |
@@ -2865,7 +2875,9 b' class InteractiveShell(SingletonConfigurable):' | |||
|
2865 | 2875 | # when this is the case, we want to run it using the pseudo_sync_runner |
|
2866 | 2876 | # so that code can invoke eventloops (for example via the %run , and |
|
2867 | 2877 | # `%paste` magic. |
|
2868 | if self.should_run_async(raw_cell) or self.loop_runner is _trio_runner: | |
|
2878 | if self.trio_runner: | |
|
2879 | runner = self.trio_runner | |
|
2880 | elif self.should_run_async(raw_cell): | |
|
2869 | 2881 | runner = self.loop_runner |
|
2870 | 2882 | else: |
|
2871 | 2883 | runner = _pseudo_sync_runner |
General Comments 0
You need to be logged in to leave comments.
Login now