##// END OF EJS Templates
Use single quotes in sql string literal (#13968)...
Use single quotes in sql string literal (#13968) the SQL spec requires that string literals use single quotes and column references (or other identifiers) use double quotes. sqlite permits the use of double quotes for string literals in "unambiguous cases". For some reason, its understanding of what constitutes unambiguous has changed recently - I'm on FreeBSD 14.0-CURRENT with sqlite 3.41.0 - and attempting to do anything with ipython throws a very strange sqlite operation error: ``` [+] ~% ipython --version (test) audrey@daisy [12:18:02 AM] 8.11.0 [+] ~% ipython (test) audrey@daisy [12:18:04 AM] [TerminalIPythonApp] ERROR | Failed to create history session in /usr/home/audrey/.ipython/profile_default/history.sqlite. History will not be saved. Traceback (most recent call last): File "/usr/home/audrey/.virtualenvs/test/lib/python3.9/site-packages/IPython/core/history.py", line 545, in __init__ self.new_session() File "/usr/home/audrey/.virtualenvs/test/lib/python3.9/site-packages/decorator.py", line 232, in fun return caller(func, *(extras + args), **kw) File "/usr/home/audrey/.virtualenvs/test/lib/python3.9/site-packages/IPython/core/history.py", line 60, in only_when_enabled return f(self, *a, **kw) File "/usr/home/audrey/.virtualenvs/test/lib/python3.9/site-packages/IPython/core/history.py", line 570, in new_session cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL, sqlite3.OperationalError: no such column: Python 3.9.16 (main, Feb 28 2023, 01:31:45) Type 'copyright', 'credits' or 'license' for more information IPython 8.11.0 -- An enhanced Interactive Python. Type '?' for help. ``` This patch fixes it. idk if this constitutes a bug in sqlite3, but this is, I guess, more correct.

File last commit:

r27387:ce62a7a4
r28168:9a5baf06 merge
Show More
async_helpers.py
156 lines | 4.2 KiB | text/x-python | PythonLexer
"""
Async helper function that are invalid syntax on Python 3.5 and below.
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.
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.
"""
import ast
import asyncio
import inspect
from functools import wraps
_asyncio_event_loop = None
def get_asyncio_loop():
"""asyncio has deprecated get_event_loop
Replicate it here, with our desired semantics:
- always returns a valid, not-closed loop
- not thread-local like asyncio's,
because we only want one loop for IPython
- if called from inside a coroutine (e.g. in ipykernel),
return the running loop
.. versionadded:: 8.0
"""
try:
return asyncio.get_running_loop()
except RuntimeError:
# not inside a coroutine,
# track our own global
pass
# not thread-local like asyncio's,
# because we only track one event loop to run for IPython itself,
# always in the main thread.
global _asyncio_event_loop
if _asyncio_event_loop is None or _asyncio_event_loop.is_closed():
_asyncio_event_loop = asyncio.new_event_loop()
return _asyncio_event_loop
class _AsyncIORunner:
def __call__(self, coro):
"""
Handler for asyncio autoawait
"""
return get_asyncio_loop().run_until_complete(coro)
def __str__(self):
return "asyncio"
_asyncio_runner = _AsyncIORunner()
class _AsyncIOProxy:
"""Proxy-object for an asyncio
Any coroutine methods will be wrapped in event_loop.run_
"""
def __init__(self, obj, event_loop):
self._obj = obj
self._event_loop = event_loop
def __repr__(self):
return f"<_AsyncIOProxy({self._obj!r})>"
def __getattr__(self, key):
attr = getattr(self._obj, key)
if inspect.iscoroutinefunction(attr):
# if it's a coroutine method,
# return a threadsafe wrapper onto the _current_ asyncio loop
@wraps(attr)
def _wrapped(*args, **kwargs):
concurrent_future = asyncio.run_coroutine_threadsafe(
attr(*args, **kwargs), self._event_loop
)
return asyncio.wrap_future(concurrent_future)
return _wrapped
else:
return attr
def __dir__(self):
return dir(self._obj)
def _curio_runner(coroutine):
"""
handler for curio autoawait
"""
import curio
return curio.run(coroutine)
def _trio_runner(async_fn):
import trio
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
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.
raise RuntimeError(
"{coro_name!r} needs a real async loop".format(coro_name=coro.__name__)
)
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.
Not handled yet: If the block of code has a return statement as the top
level, it will be seen as async. This is a know limitation.
"""
try:
code = compile(
cell, "<>", "exec", flags=getattr(ast, "PyCF_ALLOW_TOP_LEVEL_AWAIT", 0x0)
)
return inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
except (SyntaxError, MemoryError):
return False