Show More
@@ -34,7 +34,7 b' def _curio_runner(coroutine):' | |||||
34 | return curio.run(coroutine) |
|
34 | return curio.run(coroutine) | |
35 |
|
35 | |||
36 |
|
36 | |||
37 |
def _trio_runner( |
|
37 | def _trio_runner(async_fn): | |
38 | import trio |
|
38 | import trio | |
39 | async def loc(coro): |
|
39 | async def loc(coro): | |
40 | """ |
|
40 | """ | |
@@ -42,7 +42,25 b' def _trio_runner(function):' | |||||
42 | trio's internal. See https://github.com/python-trio/trio/issues/89 |
|
42 | trio's internal. See https://github.com/python-trio/trio/issues/89 | |
43 | """ |
|
43 | """ | |
44 | return await coro |
|
44 | return await coro | |
45 |
return trio.run(loc, |
|
45 | return trio.run(loc, async_fn) | |
|
46 | ||||
|
47 | ||||
|
48 | def _pseudo_sync_runner(coro): | |||
|
49 | """ | |||
|
50 | A runner that does not really allow async execution, and just advance the coroutine. | |||
|
51 | ||||
|
52 | See discussion in https://github.com/python-trio/trio/issues/608, | |||
|
53 | ||||
|
54 | Credit to Nathaniel Smith | |||
|
55 | ||||
|
56 | """ | |||
|
57 | try: | |||
|
58 | coro.send(None) | |||
|
59 | except StopIteration as exc: | |||
|
60 | return exc.value | |||
|
61 | else: | |||
|
62 | # TODO: do not raise but return an execution result with the right info. | |||
|
63 | raise RuntimeError(f"{coro.__name__!r} needs a real async loop") | |||
46 |
|
64 | |||
47 |
|
65 | |||
48 | def _asyncify(code: str) -> str: |
|
66 | def _asyncify(code: str) -> str: |
@@ -152,7 +152,7 b' def removed_co_newlocals(function:types.FunctionType) -> types.FunctionType:' | |||||
152 |
|
152 | |||
153 | # we still need to run things using the asyncio eventloop, but there is no |
|
153 | # we still need to run things using the asyncio eventloop, but there is no | |
154 | # async integration |
|
154 | # async integration | |
155 | from .async_helpers import (_asyncio_runner, _asyncify) |
|
155 | from .async_helpers import (_asyncio_runner, _asyncify, _pseudo_sync_runner) | |
156 |
|
156 | |||
157 | if sys.version_info > (3, 5): |
|
157 | if sys.version_info > (3, 5): | |
158 | from .async_helpers import _curio_runner, _trio_runner, _should_be_async |
|
158 | from .async_helpers import _curio_runner, _trio_runner, _should_be_async | |
@@ -365,9 +365,10 b' class InteractiveShell(SingletonConfigurable):' | |||||
365 | ).tag(config=True) |
|
365 | ).tag(config=True) | |
366 |
|
366 | |||
367 | loop_runner_map ={ |
|
367 | loop_runner_map ={ | |
368 | 'asyncio':_asyncio_runner, |
|
368 | 'asyncio':(_asyncio_runner, True), | |
369 | 'curio':_curio_runner, |
|
369 | 'curio':(_curio_runner, True), | |
370 | 'trio':_trio_runner, |
|
370 | 'trio':(_trio_runner, True), | |
|
371 | 'sync': (_pseudo_sync_runner, False) | |||
371 | } |
|
372 | } | |
372 |
|
373 | |||
373 | loop_runner = Any(default_value="IPython.core.interactiveshell._asyncio_runner", |
|
374 | loop_runner = Any(default_value="IPython.core.interactiveshell._asyncio_runner", | |
@@ -383,7 +384,9 b' class InteractiveShell(SingletonConfigurable):' | |||||
383 | def _import_runner(self, proposal): |
|
384 | def _import_runner(self, proposal): | |
384 | if isinstance(proposal.value, str): |
|
385 | if isinstance(proposal.value, str): | |
385 | if proposal.value in self.loop_runner_map: |
|
386 | if proposal.value in self.loop_runner_map: | |
386 |
r |
|
387 | runner, autoawait = self.loop_runner_map[proposal.value] | |
|
388 | self.autoawait = autoawait | |||
|
389 | return runner | |||
387 | runner = import_item(proposal.value) |
|
390 | runner = import_item(proposal.value) | |
388 | if not callable(runner): |
|
391 | if not callable(runner): | |
389 | raise ValueError('loop_runner must be callable') |
|
392 | raise ValueError('loop_runner must be callable') | |
@@ -2815,7 +2818,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
2815 | ) |
|
2818 | ) | |
2816 |
|
2819 | |||
2817 | @asyncio.coroutine |
|
2820 | @asyncio.coroutine | |
2818 | def run_cell_async(self, raw_cell, store_history=False, silent=False, shell_futures=True): |
|
2821 | def run_cell_async(self, raw_cell:str, store_history=False, silent=False, shell_futures=True) -> ExecutionResult: | |
2819 | """Run a complete IPython cell asynchronously. |
|
2822 | """Run a complete IPython cell asynchronously. | |
2820 |
|
2823 | |||
2821 | Parameters |
|
2824 | Parameters |
@@ -622,9 +622,14 b' class AsyncMagics(BasicMagics):' | |||||
622 | - asyncio/curio/trio activate autoawait integration and use integration |
|
622 | - asyncio/curio/trio activate autoawait integration and use integration | |
623 | with said library. |
|
623 | with said library. | |
624 |
|
624 | |||
|
625 | - `sync` turn on the pseudo-sync integration (mostly used for | |||
|
626 | `IPython.embed()` which does not run IPython with a real eventloop and | |||
|
627 | deactivate running asynchronous code. Turning on Asynchronous code with | |||
|
628 | the pseudo sync loop is undefined behavior and may lead IPython to crash. | |||
|
629 | ||||
625 | If the passed parameter does not match any of the above and is a python |
|
630 | If the passed parameter does not match any of the above and is a python | |
626 | identifier, get said object from user namespace and set it as the |
|
631 | identifier, get said object from user namespace and set it as the | |
627 | runner, and activate autoawait. |
|
632 | runner, and activate autoawait. | |
628 |
|
633 | |||
629 | If the object is a fully qualified object name, attempt to import it and |
|
634 | If the object is a fully qualified object name, attempt to import it and | |
630 | set it as the runner, and activate autoawait.""" |
|
635 | set it as the runner, and activate autoawait.""" | |
@@ -647,8 +652,7 b' class AsyncMagics(BasicMagics):' | |||||
647 | return None |
|
652 | return None | |
648 |
|
653 | |||
649 | if param in self.shell.loop_runner_map: |
|
654 | if param in self.shell.loop_runner_map: | |
650 | self.shell.loop_runner = param |
|
655 | self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param] | |
651 | self.shell.autoawait = True |
|
|||
652 | return None |
|
656 | return None | |
653 |
|
657 | |||
654 | if param in self.shell.user_ns : |
|
658 | if param in self.shell.user_ns : |
@@ -383,9 +383,9 b' def embed(**kwargs):' | |||||
383 | config = load_default_config() |
|
383 | config = load_default_config() | |
384 | config.InteractiveShellEmbed = config.TerminalInteractiveShell |
|
384 | config.InteractiveShellEmbed = config.TerminalInteractiveShell | |
385 | kwargs['config'] = config |
|
385 | kwargs['config'] = config | |
386 |
using = kwargs.get('using', ' |
|
386 | using = kwargs.get('using', 'sync') | |
387 | if using : |
|
387 | if using : | |
388 | kwargs['config'].update({'TerminalInteractiveShell':{'loop_runner':using, 'colors':'NoColor'}}) |
|
388 | kwargs['config'].update({'TerminalInteractiveShell':{'loop_runner':using, 'colors':'NoColor', 'autoawait': using!='sync'}}) | |
389 | #save ps1/ps2 if defined |
|
389 | #save ps1/ps2 if defined | |
390 | ps1 = None |
|
390 | ps1 = None | |
391 | ps2 = None |
|
391 | ps2 = None |
@@ -121,8 +121,15 b' no network request is done between ``In[1]`` and ``In[2]``.' | |||||
121 | Effects on IPython.embed() |
|
121 | Effects on IPython.embed() | |
122 | ========================== |
|
122 | ========================== | |
123 |
|
123 | |||
124 | IPython core being synchronous, the use of ``IPython.embed()`` will now require |
|
124 | IPython core being asynchronous, the use of ``IPython.embed()`` will now require | |
125 | a loop to run. This affect the ability to nest ``IPython.embed()`` which may |
|
125 | a loop to run. In order to allow ``IPython.embed()`` to be nested, as most event | |
|
126 | loops can't be nested, ``IPython.embed()`` default to a pseudo-synchronous mode, | |||
|
127 | where async code is not allowed. This mode is available in classical IPython | |||
|
128 | using ``%autoawait sync`` | |||
|
129 | ||||
|
130 | ||||
|
131 | ||||
|
132 | This affect the ability to nest ``IPython.embed()`` which may | |||
126 | require you to install alternate IO libraries like ``curio`` and ``trio`` |
|
133 | require you to install alternate IO libraries like ``curio`` and ``trio`` | |
127 |
|
134 | |||
128 |
|
135 |
General Comments 0
You need to be logged in to leave comments.
Login now