from .. import exc
+try:
+ from contextvars import copy_context as _copy_context
+
+ # If greenlet.gr_context is present in current version of greenlet,
+ # it will be set with a copy of the current context on creation.
+ # Refs: https://github.com/python-greenlet/greenlet/pull/198
+ getattr(greenlet.greenlet, "gr_context")
+except (ImportError, AttributeError):
+ _copy_context = None
+
# implementation based on snaury gist at
# https://gist.github.com/snaury/202bf4f22c41ca34e56297bae5f33fef
def __init__(self, fn, driver):
greenlet.greenlet.__init__(self, fn, driver)
self.driver = driver
+ if _copy_context is not None:
+ self.gr_context = _copy_context()
def await_only(awaitable: Coroutine) -> Any:
=lib
install_requires =
importlib-metadata;python_version<"3.8"
- greenlet;python_version>="3"
+ greenlet != 0.4.17;python_version>="3"
[options.extras_require]
asyncio =
from sqlalchemy import exc
+from sqlalchemy import testing
from sqlalchemy.testing import async_test
from sqlalchemy.testing import eq_
from sqlalchemy.testing import expect_raises_message
from sqlalchemy.util import await_only
from sqlalchemy.util import greenlet_spawn
+try:
+ from greenlet import greenlet
+except ImportError:
+ greenlet = None
+
async def run1():
return 1
await greenlet_spawn(go)
await to_await
+
+ @async_test
+ @testing.requires.python37
+ @testing.skip_if(lambda: not hasattr(greenlet, "gr_context"))
+ async def test_contextvars(self):
+ import asyncio
+ import contextvars
+
+ var = contextvars.ContextVar("var")
+ event = asyncio.Event()
+ counter = [0]
+ concurrency = 5
+
+ async def async_inner(val):
+ eq_(val, var.get())
+
+ def inner(val):
+ await_only(async_inner(val))
+ eq_(val, var.get())
+
+ async def task(val):
+ var.set(val)
+ counter[0] += 1
+ if counter[0] == concurrency:
+ event.set()
+ await event.wait()
+ await greenlet_spawn(inner, val)
+
+ done, _ = await asyncio.wait(
+ [asyncio.ensure_future(task(i)) for i in range(concurrency)]
+ )
+ for fut in done:
+ await fut
deps=pytest>=4.6.11 # this can be 6.x once we are on python 3 only
pytest-xdist
- greenlet
+ greenlet != 0.4.17
mock; python_version < '3.3'
importlib_metadata; python_version < '3.8'
postgresql: .[postgresql]