##// END OF EJS Templates
Skip problemtic test on PyPy
Skip problemtic test on PyPy

File last commit:

r27192:31475529
r27325:74e2f69f
Show More
async_helpers.py
103 lines | 2.7 KiB | text/x-python | PythonLexer
Matthias Bussonnier
Prototype async REPL using IPython, take III...
r24463 """
Async helper function that are invalid syntax on Python 3.5 and below.
Matthias Bussonnier
docs cleanup, reformat code, remove dead code.
r24490 This code is best effort, and may have edge cases not behaving as expected. In
particular it contain a number of heuristics to detect whether code is
effectively async and need to run in an event loop or not.
Matthias Bussonnier
Prototype async REPL using IPython, take III...
r24463
Matthias Bussonnier
docs cleanup, reformat code, remove dead code.
r24490 Some constructs (like top-level `return`, or `yield`) are taken care of
explicitly to actually raise a SyntaxError and stay as close as possible to
Python semantics.
Matthias Bussonnier
Prototype async REPL using IPython, take III...
r24463 """
import ast
Min RK
avoid deprecated asyncio.get_event_loop...
r27192 import asyncio
Matthias Bussonnier
workign async with
r25022 import inspect
Matthias Bussonnier
Prototype async REPL using IPython, take III...
r24463
Matthias Bussonnier
docs cleanup, reformat code, remove dead code.
r24490 class _AsyncIORunner:
Min RK
avoid deprecated asyncio.get_event_loop...
r27192 def __init__(self):
self._loop = None
@property
def loop(self):
"""Always returns a non-closed event loop"""
if self._loop is None or self._loop.is_closed():
policy = asyncio.get_event_loop_policy()
self._loop = policy.new_event_loop()
policy.set_event_loop(self._loop)
return self._loop
Matthias Bussonnier
docs cleanup, reformat code, remove dead code.
r24490 def __call__(self, coro):
"""
Handler for asyncio autoawait
"""
Min RK
avoid deprecated asyncio.get_event_loop...
r27192 return self.loop.run_until_complete(coro)
Matthias Bussonnier
reformat with black
r24474
Matthias Bussonnier
docs cleanup, reformat code, remove dead code.
r24490 def __str__(self):
Matthias Bussonnier
Remove pre-3.8 code path
r27150 return "asyncio"
Matthias Bussonnier
docs cleanup, reformat code, remove dead code.
r24490
_asyncio_runner = _AsyncIORunner()
Matthias Bussonnier
Prototype async REPL using IPython, take III...
r24463
def _curio_runner(coroutine):
"""
handler for curio autoawait
"""
import curio
Matthias Bussonnier
reformat with black
r24474
Matthias Bussonnier
Prototype async REPL using IPython, take III...
r24463 return curio.run(coroutine)
Matthias Bussonnier
Add pseudo sync mode
r24481 def _trio_runner(async_fn):
Matthias Bussonnier
att triio runner at top level now that 3.4 drop + docs
r24480 import trio
Matthias Bussonnier
docs cleanup, reformat code, remove dead code.
r24490
Matthias Bussonnier
att triio runner at top level now that 3.4 drop + docs
r24480 async def loc(coro):
"""
We need the dummy no-op async def to protect from
trio's internal. See https://github.com/python-trio/trio/issues/89
"""
return await coro
Matthias Bussonnier
docs cleanup, reformat code, remove dead code.
r24490
Matthias Bussonnier
Add pseudo sync mode
r24481 return trio.run(loc, async_fn)
def _pseudo_sync_runner(coro):
"""
A runner that does not really allow async execution, and just advance the coroutine.
See discussion in https://github.com/python-trio/trio/issues/608,
Credit to Nathaniel Smith
"""
try:
coro.send(None)
except StopIteration as exc:
return exc.value
else:
# TODO: do not raise but return an execution result with the right info.
Matthias Bussonnier
docs cleanup, reformat code, remove dead code.
r24490 raise RuntimeError(
"{coro_name!r} needs a real async loop".format(coro_name=coro.__name__)
)
Matthias Bussonnier
Prototype async REPL using IPython, take III...
r24463
def _should_be_async(cell: str) -> bool:
"""Detect if a block of code need to be wrapped in an `async def`
Attempt to parse the block of code, it it compile we're fine.
Otherwise we wrap if and try to compile.
If it works, assume it should be async. Otherwise Return False.
yangyang
catch `MemoryError` in compiling
r25429 Not handled yet: If the block of code has a return statement as the top
Matthias Bussonnier
Prototype async REPL using IPython, take III...
r24463 level, it will be seen as async. This is a know limitation.
"""
try:
Matthias Bussonnier
Remove pre-3.8 code path
r27150 code = compile(
cell, "<>", "exec", flags=getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0)
)
return inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
yangyang
catch `MemoryError` in compiling
r25429 except (SyntaxError, MemoryError):
Matthias Bussonnier
Remove pre-3.8 code path
r27150 return False