From: Mike Bayer Date: Mon, 18 Oct 2021 18:31:40 +0000 (-0400) Subject: vendor asynccontextmanager outside of greenlet dependency X-Git-Tag: rel_1_4_26~7^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aaf4643bc2734442f053216874a6b9d299a8d89e;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git vendor asynccontextmanager outside of greenlet dependency Fixed installation issue where the ``sqlalchemy.dialects.mysql`` module would not be importable if "greenlet" were not installed. This was actually breaking the sphinx build for when greenlet were not installed. Fixes: #7204 Change-Id: Ia351c124a2f1ca44bafe20a97267ce20cb55808f --- diff --git a/doc/build/changelog/unreleased_14/7204.rst b/doc/build/changelog/unreleased_14/7204.rst new file mode 100644 index 0000000000..2f02d50cd8 --- /dev/null +++ b/doc/build/changelog/unreleased_14/7204.rst @@ -0,0 +1,6 @@ +.. change:: + :tags: bug, mysql + :tickets: 7204 + + Fixed installation issue where the ``sqlalchemy.dialects.mysql`` module + would not be importable if "greenlet" were not installed. diff --git a/lib/sqlalchemy/util/_compat_py3k.py b/lib/sqlalchemy/util/_compat_py3k.py new file mode 100644 index 0000000000..cd9f3ebc34 --- /dev/null +++ b/lib/sqlalchemy/util/_compat_py3k.py @@ -0,0 +1,67 @@ +# util/_compat_py3k.py +# Copyright (C) 2005-2021 the SQLAlchemy authors and contributors +# +# +# This module is part of SQLAlchemy and is released under +# the MIT License: https://www.opensource.org/licenses/mit-license.php + +from functools import wraps + +# vendored from py3.7 + + +class _AsyncGeneratorContextManager: + """Helper for @asynccontextmanager.""" + + def __init__(self, func, args, kwds): + self.gen = func(*args, **kwds) + self.func, self.args, self.kwds = func, args, kwds + doc = getattr(func, "__doc__", None) + if doc is None: + doc = type(self).__doc__ + self.__doc__ = doc + + async def __aenter__(self): + try: + return await self.gen.__anext__() + except StopAsyncIteration: + raise RuntimeError("generator didn't yield") from None + + async def __aexit__(self, typ, value, traceback): + if typ is None: + try: + await self.gen.__anext__() + except StopAsyncIteration: + return + else: + raise RuntimeError("generator didn't stop") + else: + if value is None: + value = typ() + # See _GeneratorContextManager.__exit__ for comments on subtleties + # in this implementation + try: + await self.gen.athrow(typ, value, traceback) + raise RuntimeError("generator didn't stop after athrow()") + except StopAsyncIteration as exc: + return exc is not value + except RuntimeError as exc: + if exc is value: + return False + if isinstance(value, (StopIteration, StopAsyncIteration)): + if exc.__cause__ is value: + return False + raise + except BaseException as exc: + if exc is not value: + raise + + +# using the vendored version in all cases at the moment to establish +# full test coverage +def asynccontextmanager(func): + @wraps(func) + def helper(*args, **kwds): + return _AsyncGeneratorContextManager(func, args, kwds) + + return helper diff --git a/lib/sqlalchemy/util/_concurrency_py3k.py b/lib/sqlalchemy/util/_concurrency_py3k.py index 7a4a2c361b..55fe87c6a7 100644 --- a/lib/sqlalchemy/util/_concurrency_py3k.py +++ b/lib/sqlalchemy/util/_concurrency_py3k.py @@ -1,5 +1,11 @@ +# util/_concurrency_py3k.py +# Copyright (C) 2005-2021 the SQLAlchemy authors and contributors +# +# +# This module is part of SQLAlchemy and is released under +# the MIT License: https://www.opensource.org/licenses/mit-license.php + import asyncio -from functools import wraps import sys from typing import Any from typing import Callable @@ -194,63 +200,3 @@ def get_event_loop(): return asyncio.get_event_loop_policy().get_event_loop() else: return asyncio.get_event_loop() - - -# vendored from py3.7 - - -class _AsyncGeneratorContextManager: - """Helper for @asynccontextmanager.""" - - def __init__(self, func, args, kwds): - self.gen = func(*args, **kwds) - self.func, self.args, self.kwds = func, args, kwds - doc = getattr(func, "__doc__", None) - if doc is None: - doc = type(self).__doc__ - self.__doc__ = doc - - async def __aenter__(self): - try: - return await self.gen.__anext__() - except StopAsyncIteration: - raise RuntimeError("generator didn't yield") from None - - async def __aexit__(self, typ, value, traceback): - if typ is None: - try: - await self.gen.__anext__() - except StopAsyncIteration: - return - else: - raise RuntimeError("generator didn't stop") - else: - if value is None: - value = typ() - # See _GeneratorContextManager.__exit__ for comments on subtleties - # in this implementation - try: - await self.gen.athrow(typ, value, traceback) - raise RuntimeError("generator didn't stop after athrow()") - except StopAsyncIteration as exc: - return exc is not value - except RuntimeError as exc: - if exc is value: - return False - if isinstance(value, (StopIteration, StopAsyncIteration)): - if exc.__cause__ is value: - return False - raise - except BaseException as exc: - if exc is not value: - raise - - -# using the vendored version in all cases at the moment to establish -# full test coverage -def asynccontextmanager(func): - @wraps(func) - def helper(*args, **kwds): - return _AsyncGeneratorContextManager(func, args, kwds) - - return helper diff --git a/lib/sqlalchemy/util/concurrency.py b/lib/sqlalchemy/util/concurrency.py index 5d15e06dec..37ecfdbc33 100644 --- a/lib/sqlalchemy/util/concurrency.py +++ b/lib/sqlalchemy/util/concurrency.py @@ -1,3 +1,10 @@ +# util/concurrency.py +# Copyright (C) 2005-2021 the SQLAlchemy authors and contributors +# +# +# This module is part of SQLAlchemy and is released under +# the MIT License: https://www.opensource.org/licenses/mit-license.php + from . import compat have_greenlet = False @@ -19,7 +26,9 @@ if compat.py3k: _util_async_run_coroutine_function, ) # noqa F401, E501 from ._concurrency_py3k import asyncio # noqa F401 - from ._concurrency_py3k import asynccontextmanager + + # does not need greennlet, just Python 3 + from ._compat_py3k import asynccontextmanager # noqa F401 if not have_greenlet: @@ -58,6 +67,3 @@ if not have_greenlet: def _util_async_run_coroutine_function(fn, *arg, **kw): # noqa F81 _not_implemented() - - def asynccontextmanager(fn, *arg, **kw): # noqa F81 - _not_implemented()