summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build/changelog/unreleased_20/8842.rst19
-rw-r--r--lib/sqlalchemy/ext/asyncio/session.py27
-rw-r--r--lib/sqlalchemy/orm/session.py27
-rw-r--r--test/ext/mypy/plain_files/sessionmakers.py24
4 files changed, 97 insertions, 0 deletions
diff --git a/doc/build/changelog/unreleased_20/8842.rst b/doc/build/changelog/unreleased_20/8842.rst
new file mode 100644
index 000000000..f7e5cb729
--- /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 1956ea588..a74e87769 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 849d37ab2..15cd58792 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 ce9b76638..2d02f2a3f 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)