--- /dev/null
+.. change::
+ :tags: bug, typing
+ :tickets: 12813
+
+ Fixed typing bug where the :meth:`.Session.execute` method advertised that
+ it would return a :class:`.CursorResult` if given an insert/update/delete
+ statement. This is not the general case as several flavors of ORM
+ insert/update do not actually yield a :class:`.CursorResult` which cannot
+ be differentiated at the typing overload level, so the method now yields
+ :class:`.Result` in all cases. For those cases where
+ :class:`.CursorResult` is known to be returned and the ``.rowcount``
+ attribute is required, please use ``typing.cast()``.
from .result import AsyncScalarResult
from .session import AsyncSessionTransaction
from ...engine import Connection
- from ...engine import CursorResult
from ...engine import Engine
from ...engine import Result
from ...engine import Row
from ...orm.session import _PKIdentityArgument
from ...orm.session import _SessionBind
from ...sql.base import Executable
- from ...sql.dml import UpdateBase
from ...sql.elements import ClauseElement
from ...sql.selectable import ForUpdateParameter
from ...sql.selectable import TypedReturnsRows
_add_event: Optional[Any] = None,
) -> Result[_T]: ...
- @overload
- async def execute(
- self,
- statement: UpdateBase,
- params: Optional[_CoreAnyExecuteParams] = None,
- *,
- execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
- bind_arguments: Optional[_BindArguments] = None,
- _parent_execute_state: Optional[Any] = None,
- _add_event: Optional[Any] = None,
- ) -> CursorResult[Any]: ...
-
@overload
async def execute(
self,
from .engine import AsyncConnection
from .engine import AsyncEngine
from ...engine import Connection
- from ...engine import CursorResult
from ...engine import Engine
from ...engine import Result
from ...engine import Row
from ...orm.session import _SessionBindKey
from ...sql._typing import _InfoType
from ...sql.base import Executable
- from ...sql.dml import UpdateBase
from ...sql.elements import ClauseElement
from ...sql.selectable import ForUpdateParameter
from ...sql.selectable import TypedReturnsRows
_add_event: Optional[Any] = None,
) -> Result[_T]: ...
- @overload
- async def execute(
- self,
- statement: UpdateBase,
- params: Optional[_CoreAnyExecuteParams] = None,
- *,
- execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
- bind_arguments: Optional[_BindArguments] = None,
- _parent_execute_state: Optional[Any] = None,
- _add_event: Optional[Any] = None,
- ) -> CursorResult[Any]: ...
-
@overload
async def execute(
self,
delete_ = delete_.with_dialect_options(**delete_args)
delete_._where_criteria = self._where_criteria
- result: CursorResult[Any] = self.session.execute(
- delete_,
- self._params,
- execution_options=self._execution_options.union(
- {"synchronize_session": synchronize_session}
+ result = cast(
+ "CursorResult[Any]",
+ self.session.execute(
+ delete_,
+ self._params,
+ execution_options=self._execution_options.union(
+ {"synchronize_session": synchronize_session}
+ ),
),
)
bulk_del.result = result # type: ignore
upd = upd.with_dialect_options(**update_args)
upd._where_criteria = self._where_criteria
- result: CursorResult[Any] = self.session.execute(
- upd,
- self._params,
- execution_options=self._execution_options.union(
- {"synchronize_session": synchronize_session}
+ result = cast(
+ "CursorResult[Any]",
+ self.session.execute(
+ upd,
+ self._params,
+ execution_options=self._execution_options.union(
+ {"synchronize_session": synchronize_session}
+ ),
),
)
bulk_ud.result = result # type: ignore
from .session import sessionmaker
from .session import SessionTransaction
from ..engine import Connection
- from ..engine import CursorResult
from ..engine import Engine
from ..engine import Result
from ..engine import Row
from ..sql._typing import _T7
from ..sql._typing import _TypedColumnClauseArgument as _TCCA
from ..sql.base import Executable
- from ..sql.dml import UpdateBase
from ..sql.elements import ClauseElement
from ..sql.roles import TypedColumnsClauseRole
from ..sql.selectable import ForUpdateParameter
_add_event: Optional[Any] = None,
) -> Result[_T]: ...
- @overload
- def execute(
- self,
- statement: UpdateBase,
- params: Optional[_CoreAnyExecuteParams] = None,
- *,
- execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
- bind_arguments: Optional[_BindArguments] = None,
- _parent_execute_state: Optional[Any] = None,
- _add_event: Optional[Any] = None,
- ) -> CursorResult[Any]: ...
-
@overload
def execute(
self,
from .mapper import Mapper
from .path_registry import PathRegistry
from .query import RowReturningQuery
- from ..engine import CursorResult
from ..engine import Result
from ..engine import Row
from ..engine import RowMapping
from ..sql._typing import _TypedColumnClauseArgument as _TCCA
from ..sql.base import Executable
from ..sql.base import ExecutableOption
- from ..sql.dml import UpdateBase
from ..sql.elements import ClauseElement
from ..sql.roles import TypedColumnsClauseRole
from ..sql.selectable import ForUpdateParameter
_add_event: Optional[Any] = None,
) -> Result[_T]: ...
- @overload
- def execute(
- self,
- statement: UpdateBase,
- params: Optional[_CoreAnyExecuteParams] = None,
- *,
- execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
- bind_arguments: Optional[_BindArguments] = None,
- _parent_execute_state: Optional[Any] = None,
- _add_event: Optional[Any] = None,
- ) -> CursorResult[Any]: ...
-
@overload
def execute(
self,
def t_dml_bare_insert() -> None:
s1 = insert(User)
r1 = session.execute(s1)
- # EXPECTED_TYPE: CursorResult[Any]
+ # EXPECTED_TYPE: Result[Any]
reveal_type(r1)
- # EXPECTED_TYPE: int
- reveal_type(r1.rowcount)
def t_dml_bare_update() -> None:
s1 = update(User)
r1 = session.execute(s1)
- # EXPECTED_TYPE: CursorResult[Any]
+ # EXPECTED_TYPE: Result[Any]
reveal_type(r1)
- # EXPECTED_TYPE: int
- reveal_type(r1.rowcount)
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: Result[Any]
reveal_type(r1)
- # EXPECTED_TYPE: int
- reveal_type(r1.rowcount)
def t_dml_bare_delete() -> None:
s1 = delete(User)
r1 = session.execute(s1)
- # EXPECTED_TYPE: CursorResult[Any]
+ # EXPECTED_TYPE: Result[Any]
reveal_type(r1)
- # EXPECTED_TYPE: int
- reveal_type(r1.rowcount)
def t_dml_update() -> None: