summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build/changelog/unreleased_20/9644.rst8
-rw-r--r--lib/sqlalchemy/engine/row.py12
-rw-r--r--test/ext/mypy/plain_files/typed_results.py16
-rw-r--r--test/sql/test_resultset.py9
4 files changed, 40 insertions, 5 deletions
diff --git a/doc/build/changelog/unreleased_20/9644.rst b/doc/build/changelog/unreleased_20/9644.rst
new file mode 100644
index 000000000..f40c77917
--- /dev/null
+++ b/doc/build/changelog/unreleased_20/9644.rst
@@ -0,0 +1,8 @@
+.. change::
+ :tags: bug, typing
+ :tickets: 9644
+
+ Improved typing of :class:`_engine.RowMapping` to indicate that it
+ support also :class:`_schema.Column` as index objects, not only
+ string names.
+ Pull request curtesy or Andy Freeland.
diff --git a/lib/sqlalchemy/engine/row.py b/lib/sqlalchemy/engine/row.py
index e2690ac2d..e15ea7b17 100644
--- a/lib/sqlalchemy/engine/row.py
+++ b/lib/sqlalchemy/engine/row.py
@@ -271,9 +271,11 @@ class ROMappingView(ABC):
__slots__ = ()
_items: Sequence[Any]
- _mapping: Mapping[str, Any]
+ _mapping: Mapping["_KeyType", Any]
- def __init__(self, mapping: Mapping[str, Any], items: Sequence[Any]):
+ def __init__(
+ self, mapping: Mapping["_KeyType", Any], items: Sequence[Any]
+ ):
self._mapping = mapping
self._items = items
@@ -297,16 +299,16 @@ class ROMappingView(ABC):
class ROMappingKeysValuesView(
- ROMappingView, typing.KeysView[str], typing.ValuesView[Any]
+ ROMappingView, typing.KeysView["_KeyType"], typing.ValuesView[Any]
):
__slots__ = ("_items",)
-class ROMappingItemsView(ROMappingView, typing.ItemsView[str, Any]):
+class ROMappingItemsView(ROMappingView, typing.ItemsView["_KeyType", Any]):
__slots__ = ("_items",)
-class RowMapping(BaseRow, typing.Mapping[str, Any]):
+class RowMapping(BaseRow, typing.Mapping["_KeyType", Any]):
"""A ``Mapping`` that maps column names and objects to :class:`.Row`
values.
diff --git a/test/ext/mypy/plain_files/typed_results.py b/test/ext/mypy/plain_files/typed_results.py
index 2e42bb655..12bfcddf0 100644
--- a/test/ext/mypy/plain_files/typed_results.py
+++ b/test/ext/mypy/plain_files/typed_results.py
@@ -8,7 +8,10 @@ from sqlalchemy import column
from sqlalchemy import create_engine
from sqlalchemy import insert
from sqlalchemy import Integer
+from sqlalchemy import MetaData
from sqlalchemy import select
+from sqlalchemy import String
+from sqlalchemy import Table
from sqlalchemy import table
from sqlalchemy.ext.asyncio import AsyncConnection
from sqlalchemy.ext.asyncio import AsyncSession
@@ -31,6 +34,14 @@ class User(Base):
name: Mapped[str]
+t_user = Table(
+ "user",
+ MetaData(),
+ Column("id", Integer, primary_key=True),
+ Column("name", String),
+)
+
+
e = create_engine("sqlite://")
ae = create_async_engine("sqlite+aiosqlite://")
@@ -100,6 +111,11 @@ def t_result_ctxmanager() -> None:
reveal_type(r4)
+def t_core_mappings() -> None:
+ r = connection.execute(select(t_user)).mappings().one()
+ r.get(t_user.c.id)
+
+
def t_entity_varieties() -> None:
a1 = aliased(User)
diff --git a/test/sql/test_resultset.py b/test/sql/test_resultset.py
index 0537dc228..e382a7fb6 100644
--- a/test/sql/test_resultset.py
+++ b/test/sql/test_resultset.py
@@ -1595,6 +1595,15 @@ class CursorResultTest(fixtures.TablesTest):
r = connection.exec_driver_sql("select user_name from users").first()
eq_(len(r), 1)
+ def test_row_mapping_get(self, connection):
+ users = self.tables.users
+
+ connection.execute(users.insert(), dict(user_id=1, user_name="foo"))
+ result = connection.execute(users.select())
+ row = result.first()
+ eq_(row._mapping.get("user_id"), 1)
+ eq_(row._mapping.get(users.c.user_id), 1)
+
def test_sorting_in_python(self, connection):
users = self.tables.users