diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2023-02-26 15:34:57 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2023-02-26 20:09:07 -0500 |
| commit | 3b8123965bca6b854ccdeca79713b27136233d9a (patch) | |
| tree | e39e4595e54f96667a68b9f277ad61fd81160c9b | |
| parent | 16d3dad4490fc4915096b7963f21e6b591b15ba7 (diff) | |
| download | sqlalchemy-3b8123965bca6b854ccdeca79713b27136233d9a.tar.gz | |
use read-only Mapping for values dictionary type
Improved typing for the mapping passed to :meth:`.UpdateBase.values` to be
more open-ended about collection type, by indicating read-only ``Mapping``
instead of writeable ``Dict``, the latter of which would error out under
typing tools on too limited of a key type.
Fixes: #9376
Change-Id: Ib7fdbba05ca7e1082409e1b5616e6a010262f032
| -rw-r--r-- | doc/build/changelog/unreleased_20/9376.rst | 8 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/_typing.py | 4 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/dml.py | 3 | ||||
| -rw-r--r-- | test/ext/mypy/plain_files/dml.py | 35 |
4 files changed, 49 insertions, 1 deletions
diff --git a/doc/build/changelog/unreleased_20/9376.rst b/doc/build/changelog/unreleased_20/9376.rst new file mode 100644 index 000000000..6d63d09d4 --- /dev/null +++ b/doc/build/changelog/unreleased_20/9376.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, typing + :tickets: 9376 + + Improved typing for the mapping passed to :meth:`.UpdateBase.values` to be + more open-ended about collection type, by indicating read-only ``Mapping`` + instead of writeable ``Dict`` which would error out on too limited of a key + type. diff --git a/lib/sqlalchemy/sql/_typing.py b/lib/sqlalchemy/sql/_typing.py index 6bf9a5a1f..a828d6a0f 100644 --- a/lib/sqlalchemy/sql/_typing.py +++ b/lib/sqlalchemy/sql/_typing.py @@ -11,6 +11,7 @@ import operator from typing import Any from typing import Callable from typing import Dict +from typing import Mapping from typing import Set from typing import Tuple from typing import Type @@ -238,6 +239,9 @@ the DMLColumnRole to be able to accommodate. """ +_DMLKey = TypeVar("_DMLKey", bound=_DMLColumnArgument) +_DMLColumnKeyMapping = Mapping[_DMLKey, Any] + _DDLColumnArgument = Union[str, "Column[Any]", roles.DDLConstraintColumnRole] """DDL column. diff --git a/lib/sqlalchemy/sql/dml.py b/lib/sqlalchemy/sql/dml.py index 9042fdff7..dbbf09f1b 100644 --- a/lib/sqlalchemy/sql/dml.py +++ b/lib/sqlalchemy/sql/dml.py @@ -72,6 +72,7 @@ if TYPE_CHECKING: from ._typing import _ColumnExpressionArgument from ._typing import _ColumnsClauseArgument from ._typing import _DMLColumnArgument + from ._typing import _DMLColumnKeyMapping from ._typing import _DMLTableArgument from ._typing import _T0 # noqa from ._typing import _T1 # noqa @@ -944,7 +945,7 @@ class ValuesBase(UpdateBase): def values( self, *args: Union[ - Dict[_DMLColumnArgument, Any], + _DMLColumnKeyMapping[Any], Sequence[Any], ], **kwargs: Any, diff --git a/test/ext/mypy/plain_files/dml.py b/test/ext/mypy/plain_files/dml.py new file mode 100644 index 000000000..d2ffbf1e1 --- /dev/null +++ b/test/ext/mypy/plain_files/dml.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +from typing import Any +from typing import Dict + +from sqlalchemy import Column +from sqlalchemy import insert +from sqlalchemy.orm import DeclarativeBase +from sqlalchemy.orm import Mapped +from sqlalchemy.orm import mapped_column + + +class Base(DeclarativeBase): + pass + + +class User(Base): + __tablename__ = "user" + + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] + data: Mapped[str] + + +# test #9376 +d1: dict[str, Any] = {} +stmt1 = insert(User).values(d1) + + +d2: Dict[str, Any] = {} +stmt2 = insert(User).values(d2) + + +d3: Dict[Column[str], Any] = {} +stmt3 = insert(User).values(d3) |
