From a386d8142f5d4fcbb3b19ecad4a3ae6686fa3673 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Wed, 15 Nov 2023 18:37:49 +0200 Subject: [PATCH] update mypy tests --- lib/sqlalchemy/engine/result.py | 6 +- lib/sqlalchemy/ext/asyncio/engine.py | 17 ++-- lib/sqlalchemy/ext/asyncio/result.py | 8 +- lib/sqlalchemy/ext/asyncio/session.py | 12 +-- lib/sqlalchemy/orm/scoping.py | 6 +- lib/sqlalchemy/orm/session.py | 6 +- lib/sqlalchemy/orm/writeonly.py | 2 +- lib/sqlalchemy/sql/selectable.py | 16 ++-- test/typing/plain_files/engine/engines.py | 4 +- .../plain_files/ext/hybrid/hybrid_one.py | 2 +- test/typing/plain_files/orm/composite.py | 2 +- test/typing/plain_files/orm/composite_dc.py | 2 +- .../plain_files/orm/declared_attr_one.py | 2 +- test/typing/plain_files/orm/issue_9340.py | 4 +- test/typing/plain_files/orm/session.py | 4 +- test/typing/plain_files/orm/typed_queries.py | 78 +++++++++---------- .../plain_files/sql/common_sql_element.py | 12 +-- test/typing/plain_files/sql/functions.py | 38 ++++----- test/typing/plain_files/sql/lambda_stmt.py | 7 +- test/typing/plain_files/sql/typed_results.py | 46 +++++------ 20 files changed, 138 insertions(+), 136 deletions(-) diff --git a/lib/sqlalchemy/engine/result.py b/lib/sqlalchemy/engine/result.py index ca8b6c92f0..2b9f0282cc 100644 --- a/lib/sqlalchemy/engine/result.py +++ b/lib/sqlalchemy/engine/result.py @@ -1476,7 +1476,7 @@ class Result(_WithKeys, ResultInternal[Row[Unpack[_Ts]]]): ) @overload - def scalar_one(self: Result[Tuple[_T]]) -> _T: + def scalar_one(self: Result[_T]) -> _T: ... @overload @@ -1501,7 +1501,7 @@ class Result(_WithKeys, ResultInternal[Row[Unpack[_Ts]]]): ) @overload - def scalar_one_or_none(self: Result[Tuple[_T]]) -> Optional[_T]: + def scalar_one_or_none(self: Result[_T]) -> Optional[_T]: ... @overload @@ -1559,7 +1559,7 @@ class Result(_WithKeys, ResultInternal[Row[Unpack[_Ts]]]): ) @overload - def scalar(self: Result[Tuple[_T]]) -> Optional[_T]: + def scalar(self: Result[_T]) -> Optional[_T]: ... @overload diff --git a/lib/sqlalchemy/ext/asyncio/engine.py b/lib/sqlalchemy/ext/asyncio/engine.py index bf968cc388..b28e092175 100644 --- a/lib/sqlalchemy/ext/asyncio/engine.py +++ b/lib/sqlalchemy/ext/asyncio/engine.py @@ -41,6 +41,8 @@ from ...engine.base import NestedTransaction from ...engine.base import Transaction from ...exc import ArgumentError from ...util.concurrency import greenlet_spawn +from ...util.typing import TypeVarTuple +from ...util.typing import Unpack if TYPE_CHECKING: from ...engine.cursor import CursorResult @@ -62,6 +64,7 @@ if TYPE_CHECKING: from ...sql.selectable import TypedReturnsRows _T = TypeVar("_T", bound=Any) +_Ts = TypeVarTuple("_Ts") def create_async_engine(url: Union[str, URL], **kw: Any) -> AsyncEngine: @@ -514,11 +517,11 @@ class AsyncConnection( @overload def stream( self, - statement: TypedReturnsRows[_T], + statement: TypedReturnsRows[Unpack[_Ts]], parameters: Optional[_CoreAnyExecuteParams] = None, *, execution_options: Optional[CoreExecuteOptionsParameter] = None, - ) -> GeneratorStartableContext[AsyncResult[_T]]: + ) -> GeneratorStartableContext[AsyncResult[Unpack[_Ts]]]: ... @overload @@ -596,11 +599,11 @@ class AsyncConnection( @overload async def execute( self, - statement: TypedReturnsRows[_T], + statement: TypedReturnsRows[Unpack[_Ts]], parameters: Optional[_CoreAnyExecuteParams] = None, *, execution_options: Optional[CoreExecuteOptionsParameter] = None, - ) -> CursorResult[_T]: + ) -> CursorResult[Unpack[_Ts]]: ... @overload @@ -663,7 +666,7 @@ class AsyncConnection( @overload async def scalar( self, - statement: TypedReturnsRows[Tuple[_T]], + statement: TypedReturnsRows[_T], parameters: Optional[_CoreSingleExecuteParams] = None, *, execution_options: Optional[CoreExecuteOptionsParameter] = None, @@ -705,7 +708,7 @@ class AsyncConnection( @overload async def scalars( self, - statement: TypedReturnsRows[Tuple[_T]], + statement: TypedReturnsRows[_T], parameters: Optional[_CoreAnyExecuteParams] = None, *, execution_options: Optional[CoreExecuteOptionsParameter] = None, @@ -748,7 +751,7 @@ class AsyncConnection( @overload def stream_scalars( self, - statement: TypedReturnsRows[Tuple[_T]], + statement: TypedReturnsRows[_T], parameters: Optional[_CoreSingleExecuteParams] = None, *, execution_options: Optional[CoreExecuteOptionsParameter] = None, diff --git a/lib/sqlalchemy/ext/asyncio/result.py b/lib/sqlalchemy/ext/asyncio/result.py index 506a1fba33..4c093aa17c 100644 --- a/lib/sqlalchemy/ext/asyncio/result.py +++ b/lib/sqlalchemy/ext/asyncio/result.py @@ -326,7 +326,7 @@ class AsyncResult(_WithKeys, AsyncCommon[Row[Unpack[_Ts]]]): return await greenlet_spawn(self._only_one_row, True, False, False) @overload - async def scalar_one(self: AsyncResult[Tuple[_T]]) -> _T: + async def scalar_one(self: AsyncResult[_T]) -> _T: ... @overload @@ -350,7 +350,7 @@ class AsyncResult(_WithKeys, AsyncCommon[Row[Unpack[_Ts]]]): @overload async def scalar_one_or_none( - self: AsyncResult[Tuple[_T]], + self: AsyncResult[_T], ) -> Optional[_T]: ... @@ -405,7 +405,7 @@ class AsyncResult(_WithKeys, AsyncCommon[Row[Unpack[_Ts]]]): return await greenlet_spawn(self._only_one_row, True, True, False) @overload - async def scalar(self: AsyncResult[Tuple[_T]]) -> Optional[_T]: + async def scalar(self: AsyncResult[_T]) -> Optional[_T]: ... @overload @@ -428,7 +428,7 @@ class AsyncResult(_WithKeys, AsyncCommon[Row[Unpack[_Ts]]]): """ return await greenlet_spawn(self._only_one_row, False, False, True) - async def freeze(self) -> FrozenResult[Tuple[Unpack[_Ts]]]: + async def freeze(self) -> FrozenResult[Unpack[_Ts]]: """Return a callable object that will produce copies of this :class:`_asyncio.AsyncResult` when invoked. diff --git a/lib/sqlalchemy/ext/asyncio/session.py b/lib/sqlalchemy/ext/asyncio/session.py index 2c93525167..c9f2da46c3 100644 --- a/lib/sqlalchemy/ext/asyncio/session.py +++ b/lib/sqlalchemy/ext/asyncio/session.py @@ -394,7 +394,7 @@ class AsyncSession(ReversibleProxy[Session]): @overload async def execute( self, - statement: TypedReturnsRows[Tuple[Unpack[_Ts]]], + statement: TypedReturnsRows[Unpack[_Ts]], params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, @@ -468,7 +468,7 @@ class AsyncSession(ReversibleProxy[Session]): @overload async def scalar( self, - statement: TypedReturnsRows[Tuple[_T]], + statement: TypedReturnsRows[_T], params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, @@ -525,7 +525,7 @@ class AsyncSession(ReversibleProxy[Session]): @overload async def scalars( self, - statement: TypedReturnsRows[Tuple[_T]], + statement: TypedReturnsRows[_T], params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, @@ -652,13 +652,13 @@ class AsyncSession(ReversibleProxy[Session]): @overload async def stream( self, - statement: TypedReturnsRows[_T], + statement: TypedReturnsRows[Unpack[_Ts]], params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, bind_arguments: Optional[_BindArguments] = None, **kw: Any, - ) -> AsyncResult[_T]: + ) -> AsyncResult[Unpack[_Ts]]: ... @overload @@ -707,7 +707,7 @@ class AsyncSession(ReversibleProxy[Session]): @overload async def stream_scalars( self, - statement: TypedReturnsRows[Tuple[_T]], + statement: TypedReturnsRows[_T], params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, diff --git a/lib/sqlalchemy/orm/scoping.py b/lib/sqlalchemy/orm/scoping.py index eef50af27f..489d3af70a 100644 --- a/lib/sqlalchemy/orm/scoping.py +++ b/lib/sqlalchemy/orm/scoping.py @@ -679,7 +679,7 @@ class scoped_session(Generic[_S]): @overload def execute( self, - statement: TypedReturnsRows[Tuple[Unpack[_Ts]]], + statement: TypedReturnsRows[Unpack[_Ts]], params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, @@ -1821,7 +1821,7 @@ class scoped_session(Generic[_S]): @overload def scalar( self, - statement: TypedReturnsRows[Tuple[_T]], + statement: TypedReturnsRows[_T], params: Optional[_CoreSingleExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, @@ -1876,7 +1876,7 @@ class scoped_session(Generic[_S]): @overload def scalars( self, - statement: TypedReturnsRows[Tuple[_T]], + statement: TypedReturnsRows[_T], params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index 4828201453..031022beb8 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -2216,7 +2216,7 @@ class Session(_SessionClassMethods, EventTarget): @overload def execute( self, - statement: TypedReturnsRows[Tuple[Unpack[_Ts]]], + statement: TypedReturnsRows[Unpack[_Ts]], params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, @@ -2325,7 +2325,7 @@ class Session(_SessionClassMethods, EventTarget): @overload def scalar( self, - statement: TypedReturnsRows[Tuple[_T]], + statement: TypedReturnsRows[_T], params: Optional[_CoreSingleExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, @@ -2375,7 +2375,7 @@ class Session(_SessionClassMethods, EventTarget): @overload def scalars( self, - statement: TypedReturnsRows[Tuple[_T]], + statement: TypedReturnsRows[_T], params: Optional[_CoreAnyExecuteParams] = None, *, execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT, diff --git a/lib/sqlalchemy/orm/writeonly.py b/lib/sqlalchemy/orm/writeonly.py index 416a0399f9..fede6f780a 100644 --- a/lib/sqlalchemy/orm/writeonly.py +++ b/lib/sqlalchemy/orm/writeonly.py @@ -587,7 +587,7 @@ class WriteOnlyCollection(AbstractCollectionWriter[_T]): "produce a SQL statement and execute it with session.scalars()." ) - def select(self) -> Select[Tuple[_T]]: + def select(self) -> Select[_T]: """Produce a :class:`_sql.Select` construct that represents the rows within this instance-local :class:`_orm.WriteOnlyCollection`. diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index bc0ae88b1b..d841000548 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -5788,19 +5788,19 @@ class Select( # statically generated** by tools/generate_sel_v1_overloads.py @overload - def with_only_columns(self, __ent0: _TCCA[_T0]) -> Select[Tuple[_T0]]: + def with_only_columns(self, __ent0: _TCCA[_T0]) -> Select[_T0]: ... @overload def with_only_columns( self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1] - ) -> Select[Tuple[_T0, _T1]]: + ) -> Select[_T0, _T1]: ... @overload def with_only_columns( self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], __ent2: _TCCA[_T2] - ) -> Select[Tuple[_T0, _T1, _T2]]: + ) -> Select[_T0, _T1, _T2]: ... @overload @@ -5810,7 +5810,7 @@ class Select( __ent1: _TCCA[_T1], __ent2: _TCCA[_T2], __ent3: _TCCA[_T3], - ) -> Select[Tuple[_T0, _T1, _T2, _T3]]: + ) -> Select[_T0, _T1, _T2, _T3]: ... @overload @@ -5821,7 +5821,7 @@ class Select( __ent2: _TCCA[_T2], __ent3: _TCCA[_T3], __ent4: _TCCA[_T4], - ) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4]]: + ) -> Select[_T0, _T1, _T2, _T3, _T4]: ... @overload @@ -5833,7 +5833,7 @@ class Select( __ent3: _TCCA[_T3], __ent4: _TCCA[_T4], __ent5: _TCCA[_T5], - ) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]: + ) -> Select[_T0, _T1, _T2, _T3, _T4, _T5]: ... @overload @@ -5846,7 +5846,7 @@ class Select( __ent4: _TCCA[_T4], __ent5: _TCCA[_T5], __ent6: _TCCA[_T6], - ) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]: + ) -> Select[_T0, _T1, _T2, _T3, _T4, _T5, _T6]: ... @overload @@ -5860,7 +5860,7 @@ class Select( __ent5: _TCCA[_T5], __ent6: _TCCA[_T6], __ent7: _TCCA[_T7], - ) -> Select[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]]: + ) -> Select[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]: ... # END OVERLOADED FUNCTIONS self.with_only_columns diff --git a/test/typing/plain_files/engine/engines.py b/test/typing/plain_files/engine/engines.py index 5777b91484..7d56c51a5b 100644 --- a/test/typing/plain_files/engine/engines.py +++ b/test/typing/plain_files/engine/engines.py @@ -15,7 +15,7 @@ def regular() -> None: result = conn.execute(text("select * from table")) - # EXPECTED_TYPE: CursorResult[Any] + # EXPECTED_TYPE: CursorResult[Unpack[.*tuple[Any, ...]]] reveal_type(result) with e.begin() as conn: @@ -24,7 +24,7 @@ def regular() -> None: result = conn.execute(text("select * from table")) - # EXPECTED_TYPE: CursorResult[Any] + # EXPECTED_TYPE: CursorResult[Unpack[.*tuple[Any, ...]]] reveal_type(result) engine = create_engine("postgresql://scott:tiger@localhost/test") diff --git a/test/typing/plain_files/ext/hybrid/hybrid_one.py b/test/typing/plain_files/ext/hybrid/hybrid_one.py index 52a2a19ed0..aef41395fe 100644 --- a/test/typing/plain_files/ext/hybrid/hybrid_one.py +++ b/test/typing/plain_files/ext/hybrid/hybrid_one.py @@ -87,5 +87,5 @@ if typing.TYPE_CHECKING: # EXPECTED_TYPE: SQLCoreOperations[bool] reveal_type(expr4) - # EXPECTED_TYPE: Select[Tuple[bool]] + # EXPECTED_TYPE: Select[bool] reveal_type(stmt2) diff --git a/test/typing/plain_files/orm/composite.py b/test/typing/plain_files/orm/composite.py index 8ac1f504c2..f82bbe7c2d 100644 --- a/test/typing/plain_files/orm/composite.py +++ b/test/typing/plain_files/orm/composite.py @@ -58,7 +58,7 @@ v1 = Vertex(start=Point(3, 4), end=Point(5, 6)) stmt = select(Vertex).where(Vertex.start.in_([Point(3, 4)])) -# EXPECTED_TYPE: Select[Tuple[Vertex]] +# EXPECTED_TYPE: Select[Vertex] reveal_type(stmt) # EXPECTED_TYPE: composite.Point diff --git a/test/typing/plain_files/orm/composite_dc.py b/test/typing/plain_files/orm/composite_dc.py index fa1b16a2a6..3d8117a999 100644 --- a/test/typing/plain_files/orm/composite_dc.py +++ b/test/typing/plain_files/orm/composite_dc.py @@ -38,7 +38,7 @@ v1 = Vertex(start=Point(3, 4), end=Point(5, 6)) stmt = select(Vertex).where(Vertex.start.in_([Point(3, 4)])) -# EXPECTED_TYPE: Select[Tuple[Vertex]] +# EXPECTED_TYPE: Select[Vertex] reveal_type(stmt) # EXPECTED_TYPE: composite.Point diff --git a/test/typing/plain_files/orm/declared_attr_one.py b/test/typing/plain_files/orm/declared_attr_one.py index fc304db87e..79f1548e36 100644 --- a/test/typing/plain_files/orm/declared_attr_one.py +++ b/test/typing/plain_files/orm/declared_attr_one.py @@ -74,7 +74,7 @@ class Manager(Employee): def do_something_with_mapped_class( cls_: MappedClassProtocol[Employee], ) -> None: - # EXPECTED_TYPE: Select[Any] + # EXPECTED_TYPE: Select[Unpack[.*tuple[Any, ...]]] reveal_type(cls_.__table__.select()) # EXPECTED_TYPE: Mapper[Employee] diff --git a/test/typing/plain_files/orm/issue_9340.py b/test/typing/plain_files/orm/issue_9340.py index 72dc72df1e..20bc424ce2 100644 --- a/test/typing/plain_files/orm/issue_9340.py +++ b/test/typing/plain_files/orm/issue_9340.py @@ -40,7 +40,7 @@ def get_messages() -> Sequence[Message]: message_query = select(Message) if TYPE_CHECKING: - # EXPECTED_TYPE: Select[Tuple[Message]] + # EXPECTED_TYPE: Select[Message] reveal_type(message_query) return session.scalars(message_query).all() @@ -57,7 +57,7 @@ def get_poly_messages() -> Sequence[Message]: poly_query = select(PolymorphicMessage) if TYPE_CHECKING: - # EXPECTED_TYPE: Select[Tuple[Message]] + # EXPECTED_TYPE: Select[Message] reveal_type(poly_query) return session.scalars(poly_query).all() diff --git a/test/typing/plain_files/orm/session.py b/test/typing/plain_files/orm/session.py index 0f1c35eafa..12a261a84f 100644 --- a/test/typing/plain_files/orm/session.py +++ b/test/typing/plain_files/orm/session.py @@ -61,7 +61,7 @@ with Session(e) as sess: q2 = sess.query(User.id).filter_by(id=7) rows2 = q2.all() - # EXPECTED_TYPE: List[Row[Tuple[int]]] + # EXPECTED_TYPE: List[.*Row[.*int].*] reveal_type(rows2) # test #8280 @@ -86,7 +86,7 @@ with Session(e) as sess: # test #9125 for row in sess.query(User.id, User.name): - # EXPECTED_TYPE: Row[Tuple[int, str]] + # EXPECTED_TYPE: .*Row[int, str].* reveal_type(row) for uobj1 in sess.query(User): diff --git a/test/typing/plain_files/orm/typed_queries.py b/test/typing/plain_files/orm/typed_queries.py index e92df3eb47..47168f474b 100644 --- a/test/typing/plain_files/orm/typed_queries.py +++ b/test/typing/plain_files/orm/typed_queries.py @@ -53,12 +53,12 @@ connection = e.connect() def t_select_1() -> None: stmt = select(User.id, User.name).filter(User.id == 5) - # EXPECTED_TYPE: Select[Tuple[int, str]] + # EXPECTED_TYPE: Select[int, str] reveal_type(stmt) result = session.execute(stmt) - # EXPECTED_TYPE: Result[int, str] + # EXPECTED_TYPE: .*Result[int, str].* reveal_type(result) @@ -77,12 +77,12 @@ def t_select_2() -> None: .fetch(User.id) ) - # EXPECTED_TYPE: Select[Tuple[User]] + # EXPECTED_TYPE: Select[User] reveal_type(stmt) result = session.execute(stmt) - # EXPECTED_TYPE: Result[User] + # EXPECTED_TYPE: .*Result[User].* reveal_type(result) @@ -102,12 +102,12 @@ def t_select_3() -> None: stmt = select(ua.id, ua.name).filter(User.id == 5) - # EXPECTED_TYPE: Select[Tuple[int, str]] + # EXPECTED_TYPE: Select[int, str] reveal_type(stmt) result = session.execute(stmt) - # EXPECTED_TYPE: Result[int, str] + # EXPECTED_TYPE: .*Result[int, str].* reveal_type(result) @@ -115,7 +115,7 @@ def t_select_4() -> None: ua = aliased(User) stmt = select(ua, User).filter(User.id == 5) - # EXPECTED_TYPE: Select[Tuple[User, User]] + # EXPECTED_TYPE: Select[User, User] reveal_type(stmt) result = session.execute(stmt) @@ -137,7 +137,7 @@ def t_legacy_query_single_entity() -> None: reveal_type(q1.all()) # mypy switches to builtins.list for some reason here - # EXPECTED_RE_TYPE: .*\.[Ll]ist\[.*Row\*?\[Tuple\[.*User\]\]\] + # EXPECTED_RE_TYPE: .*\.[Ll]ist\[.*Row\*?\[.*User\].*\] reveal_type(q1.only_return_tuples(True).all()) # EXPECTED_TYPE: List[Tuple[User]] @@ -147,15 +147,15 @@ def t_legacy_query_single_entity() -> None: def t_legacy_query_cols_1() -> None: q1 = session.query(User.id, User.name).filter(User.id == 5) - # EXPECTED_TYPE: RowReturningQuery[Tuple[int, str]] + # EXPECTED_TYPE: RowReturningQuery[int, str] reveal_type(q1) - # EXPECTED_TYPE: Row[Tuple[int, str]] + # EXPECTED_TYPE: .*Row[int, str].* reveal_type(q1.one()) r1 = q1.one() - x, y = r1.t + x, y = r1 # EXPECTED_TYPE: int reveal_type(x) @@ -167,7 +167,7 @@ def t_legacy_query_cols_1() -> None: def t_legacy_query_cols_tupleq_1() -> None: q1 = session.query(User.id, User.name).filter(User.id == 5) - # EXPECTED_TYPE: RowReturningQuery[Tuple[int, str]] + # EXPECTED_TYPE: RowReturningQuery[int, str] reveal_type(q1) q2 = q1.tuples() @@ -194,15 +194,15 @@ def t_legacy_query_cols_1_with_entities() -> None: q2 = q1.with_entities(User.id, User.name) - # EXPECTED_TYPE: RowReturningQuery[Tuple[int, str]] + # EXPECTED_TYPE: RowReturningQuery[int, str] reveal_type(q2) - # EXPECTED_TYPE: Row[Tuple[int, str]] + # EXPECTED_TYPE: .*Row[int, str].* reveal_type(q2.one()) r1 = q2.one() - x, y = r1.t + x, y = r1 # EXPECTED_TYPE: int reveal_type(x) @@ -214,20 +214,20 @@ def t_legacy_query_cols_1_with_entities() -> None: def t_select_with_only_cols() -> None: q1 = select(User).where(User.id == 5) - # EXPECTED_TYPE: Select[Tuple[User]] + # EXPECTED_TYPE: Select[User] reveal_type(q1) q2 = q1.with_only_columns(User.id, User.name) - # EXPECTED_TYPE: Select[Tuple[int, str]] + # EXPECTED_TYPE: Select[int, str] reveal_type(q2) row = connection.execute(q2).one() - # EXPECTED_TYPE: Row[Tuple[int, str]] + # EXPECTED_TYPE: .*Row[int, str].* reveal_type(row) - x, y = row.t + x, y = row # EXPECTED_TYPE: int reveal_type(x) @@ -240,15 +240,15 @@ def t_legacy_query_cols_2() -> None: a1 = aliased(User) q1 = session.query(User, a1, User.name).filter(User.id == 5) - # EXPECTED_TYPE: RowReturningQuery[Tuple[User, User, str]] + # EXPECTED_TYPE: RowReturningQuery[User, User, str] reveal_type(q1) - # EXPECTED_TYPE: Row[Tuple[User, User, str]] + # EXPECTED_TYPE: .*Row[User, User, str].* reveal_type(q1.one()) r1 = q1.one() - x, y, z = r1.t + x, y, z = r1 # EXPECTED_TYPE: User reveal_type(x) @@ -269,15 +269,15 @@ def t_legacy_query_cols_2_with_entities() -> None: a1 = aliased(User) q2 = q1.with_entities(User, a1, User.name).filter(User.id == 5) - # EXPECTED_TYPE: RowReturningQuery[Tuple[User, User, str]] + # EXPECTED_TYPE: RowReturningQuery[User, User, str] reveal_type(q2) - # EXPECTED_TYPE: Row[Tuple[User, User, str]] + # EXPECTED_TYPE: .*Row[User, User, str].* reveal_type(q2.one()) r1 = q2.one() - x, y, z = r1.t + x, y, z = r1 # EXPECTED_TYPE: User reveal_type(x) @@ -295,7 +295,7 @@ def t_select_add_col_loses_type() -> None: q2 = q1.add_columns(User.data) # note this should not match Select - # EXPECTED_TYPE: Select[Any] + # EXPECTED_TYPE: Select[Unpack[.*tuple[Any, ...]]] reveal_type(q2) @@ -388,7 +388,7 @@ def t_select_w_core_selectables() -> None: # mypy would downgrade to Any rather than picking the basemost type. # with typing integrated into Select etc. we can at least get a Select # object back. - # EXPECTED_TYPE: Select[Any] + # EXPECTED_TYPE: Select[Unpack[.*tuple[Any, ...]]] reveal_type(s2) # so a fully explicit type may be given @@ -400,7 +400,7 @@ def t_select_w_core_selectables() -> None: # plain FromClause etc we at least get Select s3 = select(s1) - # EXPECTED_TYPE: Select[Any] + # EXPECTED_TYPE: Select[Unpack[.*tuple[Any, ...]]] reveal_type(s3) t1 = User.__table__ @@ -411,7 +411,7 @@ def t_select_w_core_selectables() -> None: s4 = select(t1) - # EXPECTED_TYPE: Select[Any] + # EXPECTED_TYPE: Select[Unpack[.*tuple[Any, ...]]] reveal_type(s4) @@ -420,31 +420,31 @@ def t_dml_insert() -> None: r1 = session.execute(s1) - # EXPECTED_TYPE: Result[Tuple[int, str]] + # EXPECTED_TYPE: Result[int, str] reveal_type(r1) s2 = insert(User).returning(User) r2 = session.execute(s2) - # EXPECTED_TYPE: Result[Tuple[User]] + # EXPECTED_TYPE: Result[User] reveal_type(r2) s3 = insert(User).returning(func.foo(), column("q")) - # EXPECTED_TYPE: ReturningInsert[Any] + # EXPECTED_TYPE: ReturningInsert[Unpack[.*tuple[Any, ...]]] reveal_type(s3) r3 = session.execute(s3) - # EXPECTED_TYPE: Result[Any] + # EXPECTED_TYPE: Result[Unpack[.*tuple[Any, ...]]] reveal_type(r3) def t_dml_bare_insert() -> None: s1 = insert(User) r1 = session.execute(s1) - # EXPECTED_TYPE: CursorResult[Any] + # EXPECTED_TYPE: CursorResult[Unpack[.*tuple[Any, ...]]] reveal_type(r1) # EXPECTED_TYPE: int reveal_type(r1.rowcount) @@ -453,7 +453,7 @@ def t_dml_bare_insert() -> None: def t_dml_bare_update() -> None: s1 = update(User) r1 = session.execute(s1) - # EXPECTED_TYPE: CursorResult[Any] + # EXPECTED_TYPE: CursorResult[Unpack[.*tuple[Any, ...]]] reveal_type(r1) # EXPECTED_TYPE: int reveal_type(r1.rowcount) @@ -462,7 +462,7 @@ def t_dml_bare_update() -> None: def t_dml_update_with_values() -> None: s1 = update(User).values({User.id: 123, User.data: "value"}) r1 = session.execute(s1) - # EXPECTED_TYPE: CursorResult[Any] + # EXPECTED_TYPE: CursorResult[Unpack[.*tuple[Any, ...]]] reveal_type(r1) # EXPECTED_TYPE: int reveal_type(r1.rowcount) @@ -471,7 +471,7 @@ def t_dml_update_with_values() -> None: def t_dml_bare_delete() -> None: s1 = delete(User) r1 = session.execute(s1) - # EXPECTED_TYPE: CursorResult[Any] + # EXPECTED_TYPE: CursorResult[Unpack[.*tuple[Any, ...]]] reveal_type(r1) # EXPECTED_TYPE: int reveal_type(r1.rowcount) @@ -482,7 +482,7 @@ def t_dml_update() -> None: r1 = session.execute(s1) - # EXPECTED_TYPE: Result[Tuple[int, str]] + # EXPECTED_TYPE: Result[int, str] reveal_type(r1) @@ -491,7 +491,7 @@ def t_dml_delete() -> None: r1 = session.execute(s1) - # EXPECTED_TYPE: Result[Tuple[int, str]] + # EXPECTED_TYPE: Result[int, str] reveal_type(r1) diff --git a/test/typing/plain_files/sql/common_sql_element.py b/test/typing/plain_files/sql/common_sql_element.py index 57aae8fac8..730d99bc15 100644 --- a/test/typing/plain_files/sql/common_sql_element.py +++ b/test/typing/plain_files/sql/common_sql_element.py @@ -66,7 +66,7 @@ reveal_type(e1) stmt = select(e1) -# EXPECTED_TYPE: Select[Tuple[bool]] +# EXPECTED_TYPE: Select[bool] reveal_type(stmt) stmt = stmt.where(e1) @@ -79,7 +79,7 @@ reveal_type(e2) stmt = select(e2) -# EXPECTED_TYPE: Select[Tuple[bool]] +# EXPECTED_TYPE: Select[bool] reveal_type(stmt) stmt = stmt.where(e2) @@ -89,14 +89,14 @@ stmt2 = select(User.id).order_by("id", "email").group_by("email", "id") stmt2 = ( select(User.id).order_by(asc("id"), desc("email")).group_by("email", "id") ) -# EXPECTED_TYPE: Select[Tuple[int]] +# EXPECTED_TYPE: Select[int] reveal_type(stmt2) stmt2 = select(User.id).order_by(User.id).group_by(User.email) stmt2 = ( select(User.id).order_by(User.id, User.email).group_by(User.email, User.id) ) -# EXPECTED_TYPE: Select[Tuple[int]] +# EXPECTED_TYPE: Select[int] reveal_type(stmt2) @@ -118,7 +118,7 @@ receives_bool_col_expr(user_table.c.email == "x") q1 = Session().query(User.id).order_by("email").group_by("email") q1 = Session().query(User.id).order_by("id", "email").group_by("email", "id") -# EXPECTED_TYPE: RowReturningQuery[Tuple[int]] +# EXPECTED_TYPE: RowReturningQuery[int] reveal_type(q1) q1 = Session().query(User.id).order_by(User.id).group_by(User.email) @@ -128,7 +128,7 @@ q1 = ( .order_by(User.id, User.email) .group_by(User.email, User.id) ) -# EXPECTED_TYPE: RowReturningQuery[Tuple[int]] +# EXPECTED_TYPE: RowReturningQuery[int] reveal_type(q1) # test 9174 diff --git a/test/typing/plain_files/sql/functions.py b/test/typing/plain_files/sql/functions.py index e66e554cff..b7c971b4d6 100644 --- a/test/typing/plain_files/sql/functions.py +++ b/test/typing/plain_files/sql/functions.py @@ -11,115 +11,115 @@ from sqlalchemy import select stmt1 = select(func.aggregate_strings(column("x"), column("x"))) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*str\]\] +# EXPECTED_RE_TYPE: .*Select\[.*str\] reveal_type(stmt1) stmt2 = select(func.char_length(column("x"))) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*int\]\] +# EXPECTED_RE_TYPE: .*Select\[.*int\] reveal_type(stmt2) stmt3 = select(func.concat()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*str\]\] +# EXPECTED_RE_TYPE: .*Select\[.*str\] reveal_type(stmt3) stmt4 = select(func.count(column("x"))) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*int\]\] +# EXPECTED_RE_TYPE: .*Select\[.*int\] reveal_type(stmt4) stmt5 = select(func.cume_dist()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*Decimal\]\] +# EXPECTED_RE_TYPE: .*Select\[.*Decimal\] reveal_type(stmt5) stmt6 = select(func.current_date()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*date\]\] +# EXPECTED_RE_TYPE: .*Select\[.*date\] reveal_type(stmt6) stmt7 = select(func.current_time()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*time\]\] +# EXPECTED_RE_TYPE: .*Select\[.*time\] reveal_type(stmt7) stmt8 = select(func.current_timestamp()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*datetime\]\] +# EXPECTED_RE_TYPE: .*Select\[.*datetime\] reveal_type(stmt8) stmt9 = select(func.current_user()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*str\]\] +# EXPECTED_RE_TYPE: .*Select\[.*str\] reveal_type(stmt9) stmt10 = select(func.dense_rank()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*int\]\] +# EXPECTED_RE_TYPE: .*Select\[.*int\] reveal_type(stmt10) stmt11 = select(func.localtime()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*datetime\]\] +# EXPECTED_RE_TYPE: .*Select\[.*datetime\] reveal_type(stmt11) stmt12 = select(func.localtimestamp()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*datetime\]\] +# EXPECTED_RE_TYPE: .*Select\[.*datetime\] reveal_type(stmt12) stmt13 = select(func.next_value(column("x"))) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*int\]\] +# EXPECTED_RE_TYPE: .*Select\[.*int\] reveal_type(stmt13) stmt14 = select(func.now()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*datetime\]\] +# EXPECTED_RE_TYPE: .*Select\[.*datetime\] reveal_type(stmt14) stmt15 = select(func.percent_rank()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*Decimal\]\] +# EXPECTED_RE_TYPE: .*Select\[.*Decimal\] reveal_type(stmt15) stmt16 = select(func.rank()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*int\]\] +# EXPECTED_RE_TYPE: .*Select\[.*int\] reveal_type(stmt16) stmt17 = select(func.session_user()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*str\]\] +# EXPECTED_RE_TYPE: .*Select\[.*str\] reveal_type(stmt17) stmt18 = select(func.sysdate()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*datetime\]\] +# EXPECTED_RE_TYPE: .*Select\[.*datetime\] reveal_type(stmt18) stmt19 = select(func.user()) -# EXPECTED_RE_TYPE: .*Select\[Tuple\[.*str\]\] +# EXPECTED_RE_TYPE: .*Select\[.*str\] reveal_type(stmt19) # END GENERATED FUNCTION TYPING TESTS diff --git a/test/typing/plain_files/sql/lambda_stmt.py b/test/typing/plain_files/sql/lambda_stmt.py index bce5557db8..035fde800d 100644 --- a/test/typing/plain_files/sql/lambda_stmt.py +++ b/test/typing/plain_files/sql/lambda_stmt.py @@ -1,6 +1,5 @@ from __future__ import annotations -from typing import Tuple from typing import TYPE_CHECKING from sqlalchemy import Column @@ -62,15 +61,15 @@ with e.connect() as conn: result = conn.execute(s6) if TYPE_CHECKING: - # EXPECTED_TYPE: CursorResult[Any] + # EXPECTED_TYPE: CursorResult[Unpack[.*tuple[Any, ...]]] reveal_type(result) # we can type these like this - my_result: Result[Tuple[User]] = conn.execute(s6) + my_result: Result[User] = conn.execute(s6) if TYPE_CHECKING: # pyright and mypy disagree on the specific type here, # mypy sees Result as we said, pyright seems to upgrade it to # CursorResult - # EXPECTED_RE_TYPE: .*(?:Cursor)?Result\[Tuple\[.*User\]\] + # EXPECTED_RE_TYPE: .*(?:Cursor)?Result\[.*User\] reveal_type(my_result) diff --git a/test/typing/plain_files/sql/typed_results.py b/test/typing/plain_files/sql/typed_results.py index c7842a7e79..c44c52cce6 100644 --- a/test/typing/plain_files/sql/typed_results.py +++ b/test/typing/plain_files/sql/typed_results.py @@ -87,18 +87,18 @@ reveal_type(async_session) single_stmt = select(User.name).where(User.name == "foo") -# EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[Tuple\[builtins.str\*?\]\] +# EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[builtins.str\*?\] reveal_type(single_stmt) multi_stmt = select(User.id, User.name).where(User.name == "foo") -# EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[Tuple\[builtins.int\*?, builtins.str\*?\]\] +# EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[builtins.int\*?, builtins.str\*?\] reveal_type(multi_stmt) def t_result_ctxmanager() -> None: with connection.execute(select(column("q", Integer))) as r1: - # EXPECTED_TYPE: CursorResult[Tuple[int]] + # EXPECTED_TYPE: CursorResult[int] reveal_type(r1) with r1.mappings() as r1m: @@ -110,7 +110,7 @@ def t_result_ctxmanager() -> None: reveal_type(r2) with session.execute(select(User.id)) as r3: - # EXPECTED_TYPE: Result[Tuple[int]] + # EXPECTED_TYPE: Result[int] reveal_type(r3) with session.scalars(select(User.id)) as r4: @@ -130,14 +130,14 @@ def t_entity_varieties() -> None: r1 = session.execute(s1) - # EXPECTED_RE_TYPE: sqlalchemy..*.Result\[Tuple\[builtins.int\*?, typed_results.User\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy..*.Result\[builtins.int\*?, typed_results.User\*?, builtins.str\*?\] reveal_type(r1) s2 = select(User, a1).where(User.name == "foo") r2 = session.execute(s2) - # EXPECTED_RE_TYPE: sqlalchemy.*Result\[Tuple\[typed_results.User\*?, typed_results.User\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*Result\[typed_results.User\*?, typed_results.User\*?\] reveal_type(r2) row = r2.t.one() @@ -153,18 +153,18 @@ def t_entity_varieties() -> None: # automatically typed since they are dynamically generated a1_id = cast(Mapped[int], a1.id) s3 = select(User.id, a1_id, a1, User).where(User.name == "foo") - # EXPECTED_RE_TYPE: sqlalchemy.*Select\*?\[Tuple\[builtins.int\*?, builtins.int\*?, typed_results.User\*?, typed_results.User\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*Select\*?\[builtins.int\*?, builtins.int\*?, typed_results.User\*?, typed_results.User\*?\] reveal_type(s3) # testing Mapped[entity] some_mp = cast(Mapped[User], object()) s4 = select(some_mp, a1, User).where(User.name == "foo") - # NOTEXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[Tuple\[typed_results.User\*?, typed_results.User\*?, typed_results.User\*?\]\] + # NOTEXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[typed_results.User\*?, typed_results.User\*?, typed_results.User\*?\] - # sqlalchemy.sql._gen_overloads.Select[Tuple[typed_results.User, typed_results.User, typed_results.User]] + # sqlalchemy.sql._gen_overloads.Select[typed_results.User, typed_results.User, typed_results.User] - # EXPECTED_TYPE: Select[Tuple[User, User, User]] + # EXPECTED_TYPE: Select[User, User, User] reveal_type(s4) # test plain core expressions @@ -173,30 +173,30 @@ def t_entity_varieties() -> None: s5 = select(x, y, User.name + "hi") - # EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[Tuple\[builtins.int\*?, builtins.int\*?\, builtins.str\*?]\] + # EXPECTED_RE_TYPE: sqlalchemy..*Select\*?\[builtins.int\*?, builtins.int\*?\, builtins.str\*?] reveal_type(s5) def t_ambiguous_result_type_one() -> None: stmt = select(column("q", Integer), table("x", column("y"))) - # EXPECTED_TYPE: Select[Any] + # EXPECTED_TYPE: Select[Unpack[.*tuple[Any, ...]]] reveal_type(stmt) result = session.execute(stmt) - # EXPECTED_TYPE: Result[Any] + # EXPECTED_TYPE: Result[Unpack[.*tuple[Any, ...]]] reveal_type(result) def t_ambiguous_result_type_two() -> None: stmt = select(column("q")) - # EXPECTED_TYPE: Select[Tuple[Any]] + # EXPECTED_TYPE: Select[Any] reveal_type(stmt) result = session.execute(stmt) - # EXPECTED_TYPE: Result[Any] + # EXPECTED_TYPE: Result[Unpack[.*tuple[Any, ...]]] reveal_type(result) @@ -204,11 +204,11 @@ def t_aliased() -> None: a1 = aliased(User) s1 = select(a1) - # EXPECTED_TYPE: Select[Tuple[User]] + # EXPECTED_TYPE: Select[User] reveal_type(s1) s4 = select(a1.name, a1, a1, User).where(User.name == "foo") - # EXPECTED_TYPE: Select[Tuple[str, User, User, User]] + # EXPECTED_TYPE: Select[str, User, User, User] reveal_type(s4) @@ -341,11 +341,11 @@ async def t_async_result_insertmanyvalues_scalars() -> None: def t_connection_execute_multi_row_t() -> None: result = connection.execute(multi_stmt) - # EXPECTED_RE_TYPE: sqlalchemy.*CursorResult\[Tuple\[builtins.int\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: sqlalchemy.*CursorResult\[builtins.int\*?, builtins.str\*?\] reveal_type(result) row = result.one() - # EXPECTED_RE_TYPE: sqlalchemy.*Row\[Tuple\[builtins.int\*?, builtins.str\*?\]\] + # EXPECTED_RE_TYPE: .*sqlalchemy.*Row\[builtins.int\*?, builtins.str\*?\].* reveal_type(row) x, y = row.t @@ -681,18 +681,18 @@ def test_outerjoin_10173() -> None: id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] - stmt: Select[Tuple[User, Other]] = select(User, Other).outerjoin( + stmt: Select[User, Other] = select(User, Other).outerjoin( Other, User.id == Other.id ) - stmt2: Select[Tuple[User, Optional[Other]]] = select( + stmt2: Select[User, Optional[Other]] = select( User, Nullable(Other) ).outerjoin(Other, User.id == Other.id) - stmt3: Select[Tuple[int, Optional[str]]] = select( + stmt3: Select[int, Optional[str]] = select( User.id, Nullable(Other.name) ).outerjoin(Other, User.id == Other.id) def go(W: Optional[Type[Other]]) -> None: - stmt4: Select[Tuple[str, Other]] = select( + stmt4: Select[str, Other] = select( NotNullable(User.value), NotNullable(W) ).where(User.value.is_not(None)) print(stmt4) -- 2.47.3