]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
write out a full doc for both run_sync methods
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 26 Apr 2023 19:32:56 +0000 (15:32 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 26 Apr 2023 19:32:56 +0000 (15:32 -0400)
Fixes: #9705
Change-Id: I705463b9984f207f2268da6ebd80f07b68aa08f0

lib/sqlalchemy/ext/asyncio/engine.py
lib/sqlalchemy/ext/asyncio/session.py

index 6dfca463fb79beced000afe276a2665c6e0c7e3d..531abdde52ea04d8aef5271d9e8f30e3a6534ee7 100644 (file)
@@ -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)
 
index dabe1824e285453d4d8e7456e56206c44ae2ae76..d819f546c567d978a9bdb189bc17aa14afa0e7d5 100644 (file)
@@ -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)