From: Mike Bayer Date: Fri, 4 Aug 2023 00:14:39 +0000 (-0400) Subject: apply correct type to orm connection.execution_options X-Git-Tag: rel_2_0_20~20^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=022d148a7d969ee7a645e368d905862087bd0fd3;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git apply correct type to orm connection.execution_options Fixed issue in :class:`_orm.Session` and :class:`_asyncio.AsyncSession` methods such as :meth:`_orm.Session.connection` where the :paramref:`_orm.Session.connection.execution_options` parameter were hardcoded to an internal type that is not user-facing. Fixes: #10182 Change-Id: Iab9d510bf182c7dfc0521c948cf63396d05078e5 --- diff --git a/doc/build/changelog/unreleased_20/10182.rst b/doc/build/changelog/unreleased_20/10182.rst new file mode 100644 index 0000000000..74e4a25883 --- /dev/null +++ b/doc/build/changelog/unreleased_20/10182.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, typing + :tickets: 10182 + + Fixed issue in :class:`_orm.Session` and :class:`_asyncio.AsyncSession` + methods such as :meth:`_orm.Session.connection` where the + :paramref:`_orm.Session.connection.execution_options` parameter were + hardcoded to an internal type that is not user-facing. diff --git a/lib/sqlalchemy/ext/asyncio/scoping.py b/lib/sqlalchemy/ext/asyncio/scoping.py index ec99a20238..155da8f4c9 100644 --- a/lib/sqlalchemy/ext/asyncio/scoping.py +++ b/lib/sqlalchemy/ext/asyncio/scoping.py @@ -43,7 +43,7 @@ if TYPE_CHECKING: from ...engine import Row from ...engine import RowMapping from ...engine.interfaces import _CoreAnyExecuteParams - from ...engine.interfaces import _ExecuteOptions + from ...engine.interfaces import CoreExecuteOptionsParameter from ...engine.result import ScalarResult from ...orm._typing import _IdentityKeyType from ...orm._typing import _O @@ -488,7 +488,7 @@ class async_scoped_session(Generic[_AS]): async def connection( self, bind_arguments: Optional[_BindArguments] = None, - execution_options: Optional[_ExecuteOptions] = None, + execution_options: Optional[CoreExecuteOptionsParameter] = None, **kw: Any, ) -> AsyncConnection: r"""Return a :class:`_asyncio.AsyncConnection` object corresponding to diff --git a/lib/sqlalchemy/ext/asyncio/session.py b/lib/sqlalchemy/ext/asyncio/session.py index 02631cfebf..3d176b4e7b 100644 --- a/lib/sqlalchemy/ext/asyncio/session.py +++ b/lib/sqlalchemy/ext/asyncio/session.py @@ -48,7 +48,7 @@ if TYPE_CHECKING: from ...engine import RowMapping from ...engine import ScalarResult from ...engine.interfaces import _CoreAnyExecuteParams - from ...engine.interfaces import _ExecuteOptions + from ...engine.interfaces import CoreExecuteOptionsParameter from ...event import dispatcher from ...orm._typing import _IdentityKeyType from ...orm._typing import _O @@ -870,7 +870,7 @@ class AsyncSession(ReversibleProxy[Session]): async def connection( self, bind_arguments: Optional[_BindArguments] = None, - execution_options: Optional[_ExecuteOptions] = None, + execution_options: Optional[CoreExecuteOptionsParameter] = None, **kw: Any, ) -> AsyncConnection: r"""Return a :class:`_asyncio.AsyncConnection` object corresponding to diff --git a/lib/sqlalchemy/orm/scoping.py b/lib/sqlalchemy/orm/scoping.py index 4230a890c1..2fbd4fbe51 100644 --- a/lib/sqlalchemy/orm/scoping.py +++ b/lib/sqlalchemy/orm/scoping.py @@ -55,7 +55,7 @@ if TYPE_CHECKING: from ..engine import RowMapping from ..engine.interfaces import _CoreAnyExecuteParams from ..engine.interfaces import _CoreSingleExecuteParams - from ..engine.interfaces import _ExecuteOptions + from ..engine.interfaces import CoreExecuteOptionsParameter from ..engine.result import ScalarResult from ..sql._typing import _ColumnsClauseArgument from ..sql._typing import _T0 @@ -554,7 +554,7 @@ class scoped_session(Generic[_S]): def connection( self, bind_arguments: Optional[_BindArguments] = None, - execution_options: Optional[_ExecuteOptions] = None, + execution_options: Optional[CoreExecuteOptionsParameter] = None, ) -> Connection: r"""Return a :class:`_engine.Connection` object corresponding to this :class:`.Session` object's transactional state. diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index 8d19e2374e..fade4c4884 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -109,6 +109,7 @@ if typing.TYPE_CHECKING: from ..engine.interfaces import _CoreAnyExecuteParams from ..engine.interfaces import _CoreSingleExecuteParams from ..engine.interfaces import _ExecuteOptions + from ..engine.interfaces import CoreExecuteOptionsParameter from ..engine.result import ScalarResult from ..event import _InstanceLevelDispatch from ..sql._typing import _ColumnsClauseArgument @@ -1089,7 +1090,7 @@ class SessionTransaction(_StateChange, TransactionalContext): def _connection_for_bind( self, bind: _SessionBind, - execution_options: Optional[_ExecuteOptions], + execution_options: Optional[CoreExecuteOptionsParameter], ) -> Connection: if bind in self._connections: if execution_options: @@ -1939,7 +1940,7 @@ class Session(_SessionClassMethods, EventTarget): def connection( self, bind_arguments: Optional[_BindArguments] = None, - execution_options: Optional[_ExecuteOptions] = None, + execution_options: Optional[CoreExecuteOptionsParameter] = None, ) -> Connection: r"""Return a :class:`_engine.Connection` object corresponding to this :class:`.Session` object's transactional state. @@ -1987,7 +1988,7 @@ class Session(_SessionClassMethods, EventTarget): def _connection_for_bind( self, engine: _SessionBind, - execution_options: Optional[_ExecuteOptions] = None, + execution_options: Optional[CoreExecuteOptionsParameter] = None, **kw: Any, ) -> Connection: TransactionalContext._trans_ctx_check(self) diff --git a/test/typing/plain_files/orm/session.py b/test/typing/plain_files/orm/session.py index 7a26835d32..0f1c35eafa 100644 --- a/test/typing/plain_files/orm/session.py +++ b/test/typing/plain_files/orm/session.py @@ -136,3 +136,35 @@ async def test_with_for_update_async() -> None: await ss.refresh(u1) await ss.refresh(u1, with_for_update=True) + + +def test_exec_options() -> None: + """test #10182""" + + session = Session() + + session.connection( + execution_options={"isolation_level": "REPEATABLE READ"} + ) + + scoped = scoped_session(sessionmaker()) + + scoped.connection(execution_options={"isolation_level": "REPEATABLE READ"}) + + +async def async_test_exec_options() -> None: + """test #10182""" + + session = AsyncSession() + + await session.connection( + execution_options={"isolation_level": "REPEATABLE READ"} + ) + + scoped = async_scoped_session( + async_sessionmaker(), scopefunc=asyncio.current_task + ) + + await scoped.connection( + execution_options={"isolation_level": "REPEATABLE READ"} + )