From: Sam Bull Date: Sun, 20 Nov 2022 00:38:04 +0000 (-0500) Subject: Fix inferred type of async_sessionmaker X-Git-Tag: rel_2_0_0b4~45^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e43e240a0088ac429eb551c7ea1c537c266b4853;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Fix inferred type of async_sessionmaker Improved the typing for :class:`.sessionmaker` and :class:`.asyncsessionmaker`, so that the default type of their return value will be :class:`.Session` or :class:`.AsyncSession`, without the need to type this explicitly. Previously, Mypy would not automaticaly infer these return types from its generic base. As part of this change, arguments for :class:`.Session`, :class:`.AsyncSession`, :class:`.sessionmaker` and :class:`.asyncsessionmaker` beyond the initial "bind" argument have been made keyword-only, which includes parameters that have always been documented as keyword arguments, such as :paramref:`.Session.autoflush`, :paramref:`.Session.class_`, etc. Pull request courtesy Sam Bull. Closes: #8842 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/8842 Pull-request-sha: fa6d1a8468e98b40e12f82ed7ddaddc1fde060ac Change-Id: Iaaabc4572a87489d61617d970f62b9b50db4fac7 --- diff --git a/doc/build/changelog/unreleased_20/8842.rst b/doc/build/changelog/unreleased_20/8842.rst new file mode 100644 index 0000000000..f7e5cb7299 --- /dev/null +++ b/doc/build/changelog/unreleased_20/8842.rst @@ -0,0 +1,19 @@ +.. change:: + :tags: bug, typing + :tickets: 8842 + + Improved the typing for :class:`.sessionmaker` and + :class:`.asyncsessionmaker`, so that the default type of their return value + will be :class:`.Session` or :class:`.AsyncSession`, without the need to + type this explicitly. Previously, Mypy would not automaticaly infer these + return types from its generic base. + + As part of this change, arguments for :class:`.Session`, + :class:`.AsyncSession`, :class:`.sessionmaker` and + :class:`.asyncsessionmaker` beyond the initial "bind" argument have been + made keyword-only, which includes parameters that have always been + documented as keyword arguments, such as :paramref:`.Session.autoflush`, + :paramref:`.Session.class_`, etc. + + Pull request courtesy Sam Bull. + diff --git a/lib/sqlalchemy/ext/asyncio/session.py b/lib/sqlalchemy/ext/asyncio/session.py index 1956ea588a..a74e877695 100644 --- a/lib/sqlalchemy/ext/asyncio/session.py +++ b/lib/sqlalchemy/ext/asyncio/session.py @@ -124,6 +124,7 @@ class AsyncSession(ReversibleProxy[Session]): def __init__( self, bind: Optional[_AsyncSessionBind] = None, + *, binds: Optional[Dict[_SessionBindKey, _AsyncSessionBind]] = None, sync_session_class: Optional[Type[Session]] = None, **kw: Any, @@ -1436,9 +1437,35 @@ class async_sessionmaker(Generic[_AS]): class_: Type[_AS] + @overload + def __init__( + self, + bind: Optional[_AsyncSessionBind] = ..., + *, + class_: Type[_AS], + autoflush: bool = ..., + expire_on_commit: bool = ..., + info: Optional[_InfoType] = ..., + **kw: Any, + ): + ... + + @overload + def __init__( + self: "async_sessionmaker[AsyncSession]", + bind: Optional[_AsyncSessionBind] = ..., + *, + autoflush: bool = ..., + expire_on_commit: bool = ..., + info: Optional[_InfoType] = ..., + **kw: Any, + ): + ... + def __init__( self, bind: Optional[_AsyncSessionBind] = None, + *, class_: Type[_AS] = AsyncSession, # type: ignore autoflush: bool = True, expire_on_commit: bool = True, diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index 849d37ab22..15cd587926 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -1362,6 +1362,7 @@ class Session(_SessionClassMethods, EventTarget): def __init__( self, bind: Optional[_SessionBind] = None, + *, autoflush: bool = True, future: Literal[True] = True, expire_on_commit: bool = True, @@ -4621,9 +4622,35 @@ class sessionmaker(_SessionClassMethods, Generic[_S]): class_: Type[_S] + @overload + def __init__( + self, + bind: Optional[_SessionBind] = ..., + *, + class_: Type[_S], + autoflush: bool = ..., + expire_on_commit: bool = ..., + info: Optional[_InfoType] = ..., + **kw: Any, + ): + ... + + @overload + def __init__( + self: "sessionmaker[Session]", + bind: Optional[_SessionBind] = ..., + *, + autoflush: bool = ..., + expire_on_commit: bool = ..., + info: Optional[_InfoType] = ..., + **kw: Any, + ): + ... + def __init__( self, bind: Optional[_SessionBind] = None, + *, class_: Type[_S] = Session, # type: ignore autoflush: bool = True, expire_on_commit: bool = True, diff --git a/test/ext/mypy/plain_files/sessionmakers.py b/test/ext/mypy/plain_files/sessionmakers.py index ce9b766385..2d02f2a3f4 100644 --- a/test/ext/mypy/plain_files/sessionmakers.py +++ b/test/ext/mypy/plain_files/sessionmakers.py @@ -86,3 +86,27 @@ def main() -> None: sess = scoped_fac() # EXPECTED_TYPE: MySession reveal_type(sess) + + +def test_8837_sync() -> None: + sm = sessionmaker() + + # EXPECTED_TYPE: sessionmaker[Session] + reveal_type(sm) + + session = sm() + + # EXPECTED_TYPE: Session + reveal_type(session) + + +def test_8837_async() -> None: + as_ = async_sessionmaker() + + # EXPECTED_TYPE: async_sessionmaker[AsyncSession] + reveal_type(as_) + + async_session = as_() + + # EXPECTED_TYPE: AsyncSession + reveal_type(async_session)