From: Mike Bayer Date: Wed, 26 Apr 2023 19:32:56 +0000 (-0400) Subject: write out a full doc for both run_sync methods X-Git-Tag: rel_2_0_11~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a54ab6944e66830d99d7fd09a82766c392731920;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git write out a full doc for both run_sync methods Fixes: #9705 Change-Id: I705463b9984f207f2268da6ebd80f07b68aa08f0 --- diff --git a/lib/sqlalchemy/ext/asyncio/engine.py b/lib/sqlalchemy/ext/asyncio/engine.py index 6dfca463fb..531abdde52 100644 --- a/lib/sqlalchemy/ext/asyncio/engine.py +++ b/lib/sqlalchemy/ext/asyncio/engine.py @@ -776,14 +776,50 @@ class AsyncConnection( async def run_sync( self, fn: Callable[..., Any], *arg: Any, **kw: Any ) -> Any: - """Invoke the given sync callable passing self as the first argument. + """Invoke the given synchronous (i.e. not async) callable, + passing a synchronous-style :class:`_engine.Connection` as the first + argument. + + This method allows traditional synchronous SQLAlchemy functions to + run within the context of an asyncio application. + + E.g.:: + + def do_something_with_core(conn: Connection, arg1: int, arg2: str) -> str: + '''A synchronous function that does not require awaiting + + :param conn: a Core SQLAlchemy Connection, used synchronously + + :return: an optional return value is supported + + ''' + conn.execute( + some_table.insert().values(int_col=arg1, str_col=arg2) + ) + return "success" + + + async def do_something_async(async_engine: AsyncEngine) -> None: + '''an async function that uses awaiting''' + + async with async_engine.begin() as async_conn: + # run do_something_with_core() with a sync-style + # Connection, proxied into an awaitable + return_code = await async_conn.run_sync(do_something_with_core, 5, "strval") + print(return_code) This method maintains the asyncio event loop all the way through to the database connection by running the given callable in a specially instrumented greenlet. - E.g.:: + The most rudimentary use of :meth:`.AsyncConnection.run_sync` is to + invoke methods such as :meth:`_schema.MetaData.create_all`, given + an :class:`.AsyncConnection` that needs to be provided to + :meth:`_schema.MetaData.create_all` as a :class:`_engine.Connection` + object:: + # run metadata.create_all(conn) with a sync-style Connection, + # proxied into an awaitable with async_engine.begin() as conn: await conn.run_sync(metadata.create_all) @@ -796,8 +832,11 @@ class AsyncConnection( .. seealso:: + :meth:`.AsyncSession.run_sync` + :ref:`session_run_sync` - """ + + """ # noqa: E501 return await greenlet_spawn(fn, self._proxied, *arg, **kw) diff --git a/lib/sqlalchemy/ext/asyncio/session.py b/lib/sqlalchemy/ext/asyncio/session.py index dabe1824e2..d819f546c5 100644 --- a/lib/sqlalchemy/ext/asyncio/session.py +++ b/lib/sqlalchemy/ext/asyncio/session.py @@ -233,17 +233,40 @@ class AsyncSession(ReversibleProxy[Session]): async def run_sync( self, fn: Callable[..., Any], *arg: Any, **kw: Any ) -> Any: - """Invoke the given sync callable passing sync self as the first + """Invoke the given synchronous (i.e. not async) callable, + passing a synchronous-style :class:`_orm.Session` as the first argument. - This method maintains the asyncio event loop all the way through - to the database connection by running the given callable in a - specially instrumented greenlet. + This method allows traditional synchronous SQLAlchemy functions to + run within the context of an asyncio application. E.g.:: - with AsyncSession(async_engine) as session: - await session.run_sync(some_business_method) + def some_business_method(session: Session, param: str) -> str: + '''A synchronous function that does not require awaiting + + :param session: a SQLAlchemy Session, used synchronously + + :return: an optional return value is supported + + ''' + session.add(MyObject(param=param)) + session.flush() + return "success" + + + async def do_something_async(async_engine: AsyncEngine) -> None: + '''an async function that uses awaiting''' + + with AsyncSession(async_engine) as async_session: + # run some_business_method() with a sync-style + # Session, proxied into an awaitable + return_code = await async_session.run_sync(some_business_method, param="param1") + print(return_code) + + This method maintains the asyncio event loop all the way through + to the database connection by running the given callable in a + specially instrumented greenlet. .. note:: @@ -254,8 +277,10 @@ class AsyncSession(ReversibleProxy[Session]): .. seealso:: + :meth:`.AsyncConnection.run_sync` + :ref:`session_run_sync` - """ + """ # noqa: E501 return await greenlet_spawn(fn, self.sync_session, *arg, **kw)