]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
update mypy tests
authorYurii Karabas <1998uriyyo@gmail.com>
Wed, 15 Nov 2023 16:37:49 +0000 (18:37 +0200)
committerYurii Karabas <1998uriyyo@gmail.com>
Wed, 15 Nov 2023 16:37:49 +0000 (18:37 +0200)
20 files changed:
lib/sqlalchemy/engine/result.py
lib/sqlalchemy/ext/asyncio/engine.py
lib/sqlalchemy/ext/asyncio/result.py
lib/sqlalchemy/ext/asyncio/session.py
lib/sqlalchemy/orm/scoping.py
lib/sqlalchemy/orm/session.py
lib/sqlalchemy/orm/writeonly.py
lib/sqlalchemy/sql/selectable.py
test/typing/plain_files/engine/engines.py
test/typing/plain_files/ext/hybrid/hybrid_one.py
test/typing/plain_files/orm/composite.py
test/typing/plain_files/orm/composite_dc.py
test/typing/plain_files/orm/declared_attr_one.py
test/typing/plain_files/orm/issue_9340.py
test/typing/plain_files/orm/session.py
test/typing/plain_files/orm/typed_queries.py
test/typing/plain_files/sql/common_sql_element.py
test/typing/plain_files/sql/functions.py
test/typing/plain_files/sql/lambda_stmt.py
test/typing/plain_files/sql/typed_results.py

index ca8b6c92f0611924c68ac7d5e975bf722221e19e..2b9f0282cc7bc3e3a135cc2af1e5a7e78ab80c59 100644 (file)
@@ -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
index bf968cc38848dafe7a5642facdf1bcc27eac774e..b28e0921756b5d36358fb9c9945131ebfff48540 100644 (file)
@@ -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,
index 506a1fba331b0afcc2781a49170c5f6f2780b6f4..4c093aa17cfd0b37c9e1b5f6fce726389ec935d4 100644 (file)
@@ -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.
 
index 2c93525167e017893219a79d6d7778f7069fea8a..c9f2da46c3ce3ec9136f569d8914c1acc10c317d 100644 (file)
@@ -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,
index eef50af27ff7f8c42d696fca62c3ebcf1f052db0..489d3af70a717e0bb0422788569fe2e165a336ab 100644 (file)
@@ -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,
index 4828201453266c0632e37bb02c0f52e2f09c9c3b..031022beb82d43fe624177c02be0425754943c30 100644 (file)
@@ -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,
index 416a0399f93ea3bbcc6b97d1f0e4fd5dc6b2448d..fede6f780a9f3a698113dbe0d8ac289e04ca7ad2 100644 (file)
@@ -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`.
 
index bc0ae88b1bbef58a265c4fa522074152e5e18765..d84100054891fa68af89de48c8d5fe5e93121caf 100644 (file)
@@ -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
index 5777b91484180aaa6784f53485c9b2729fb0f7e0..7d56c51a5bb7023c9106820f98b2451a45257bd3 100644 (file)
@@ -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")
index 52a2a19ed0cee04be85d23e1fef6b244cf43348a..aef41395fee4b85d72cd2dda2286b84b4c9a1b8c 100644 (file)
@@ -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)
index 8ac1f504c26b4bc809dea1811cb61b4b9cc50f0e..f82bbe7c2dfd7d40d992cd11ac2b85af42dd50e3 100644 (file)
@@ -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
index fa1b16a2a67ee0b6d463cae36782951bd7ea6a9d..3d8117a999a79e5a7edc1110687c7f8437f5ee93 100644 (file)
@@ -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
index fc304db87e97ca0cf852a21cf23075eb865f9e7c..79f1548e36504653181da2ccd6ced4fc11266054 100644 (file)
@@ -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]
index 72dc72df1ecd668fefc859be48020420aa5f4b92..20bc424ce24975443d79edb94bc540fd30d8470d 100644 (file)
@@ -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()
index 0f1c35eafa13598e12b15e982388bbaf13088cbc..12a261a84f7cb7afdffb23dacbfe926ce1134014 100644 (file)
@@ -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):
index e92df3eb47e10fa04965d027ddc4d7761130fc59..47168f474bb1e1c6e317d3af827f95f812b62bc3 100644 (file)
@@ -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)
 
 
index 57aae8fac81895b673c082d2a49023857ce5d80d..730d99bc1512470178d29003d90842e9f40a4d08 100644 (file)
@@ -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
index e66e554cff78cb2a3833ffddbdc59fa765983009..b7c971b4d6a6418081a42ffae2e875cbe8387c64 100644 (file)
@@ -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
index bce5557db8d6209aa3674b264be3f3d84061bd32..035fde800d5d0da612c0bf70a3ec478d62702ef8 100644 (file)
@@ -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)
index c7842a7e7995d0407d46b1b94c73a67b92e6ada2..c44c52cce631618ae9eb9ffd55d9876025589e9b 100644 (file)
@@ -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)