From 16be119cc04d9327df78e0891bec40765bfd5d4f Mon Sep 17 00:00:00 2001 From: Federico Caselli Date: Thu, 9 Oct 2025 20:45:26 +0200 Subject: [PATCH] Improve typing and code in cursor module Change-Id: I56b89f303f03dfc7056c7174ac06bc1679319bb5 --- lib/sqlalchemy/engine/cursor.py | 47 +++++++++++++++------------------ 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/lib/sqlalchemy/engine/cursor.py b/lib/sqlalchemy/engine/cursor.py index 35d8180ac0..5fcc93150e 100644 --- a/lib/sqlalchemy/engine/cursor.py +++ b/lib/sqlalchemy/engine/cursor.py @@ -20,6 +20,7 @@ from typing import Any from typing import cast from typing import ClassVar from typing import Dict +from typing import Final from typing import Iterable from typing import Iterator from typing import List @@ -80,45 +81,45 @@ _Ts = TypeVarTuple("_Ts") # using raw tuple is faster than namedtuple. # these match up to the positions in # _CursorKeyMapRecType -MD_INDEX: Literal[0] = 0 +MD_INDEX: Final[Literal[0]] = 0 """integer index in cursor.description """ -MD_RESULT_MAP_INDEX: Literal[1] = 1 +MD_RESULT_MAP_INDEX: Final[Literal[1]] = 1 """integer index in compiled._result_columns""" -MD_OBJECTS: Literal[2] = 2 +MD_OBJECTS: Final[Literal[2]] = 2 """other string keys and ColumnElement obj that can match. This comes from compiler.RM_OBJECTS / compiler.ResultColumnsEntry.objects """ -MD_LOOKUP_KEY: Literal[3] = 3 +MD_LOOKUP_KEY: Final[Literal[3]] = 3 """string key we usually expect for key-based lookup this comes from compiler.RM_NAME / compiler.ResultColumnsEntry.name """ -MD_RENDERED_NAME: Literal[4] = 4 +MD_RENDERED_NAME: Final[Literal[4]] = 4 """name that is usually in cursor.description this comes from compiler.RENDERED_NAME / compiler.ResultColumnsEntry.keyname """ -MD_PROCESSOR: Literal[5] = 5 +MD_PROCESSOR: Final[Literal[5]] = 5 """callable to process a result value into a row""" -MD_UNTRANSLATED: Literal[6] = 6 +MD_UNTRANSLATED: Final[Literal[6]] = 6 """raw name from cursor.description""" _CursorKeyMapRecType = Tuple[ Optional[int], # MD_INDEX, None means the record is ambiguously named - int, # MD_RESULT_MAP_INDEX + int, # MD_RESULT_MAP_INDEX, -1 if MD_INDEX is None List[Any], # MD_OBJECTS str, # MD_LOOKUP_KEY str, # MD_RENDERED_NAME @@ -222,21 +223,17 @@ class CursorResultMetaData(ResultMetaData): def _splice_horizontally(self, other: CursorResultMetaData) -> Self: keymap = dict(self._keymap) offset = len(self._keys) - keymap.update( - { - key: ( - # int index should be None for ambiguous key - ( - value[0] + offset - if value[0] is not None and key not in keymap - else None - ), - value[1] + offset, - *value[2:], - ) - for key, value in other._keymap.items() - } - ) + + for key, value in other._keymap.items(): + # int index should be None for ambiguous key + if value[MD_INDEX] is not None and key not in keymap: + md_index = value[MD_INDEX] + offset + md_object = value[MD_RESULT_MAP_INDEX] + offset + else: + md_index = None + md_object = -1 + keymap[key] = (md_index, md_object, *value[2:]) + self_tf = self._tuplefilter other_tf = other._tuplefilter @@ -428,7 +425,7 @@ class CursorResultMetaData(ResultMetaData): # column keys and other names if num_ctx_cols: # keymap by primary string... - by_key = { + by_key: Dict[str, _CursorKeyMapRecType] = { metadata_entry[MD_LOOKUP_KEY]: metadata_entry for metadata_entry in raw } @@ -474,7 +471,7 @@ class CursorResultMetaData(ResultMetaData): # record into by_key. by_key.update( { - key: (None, None, [], key, key, None, None) + key: (None, -1, [], key, key, None, None) for key in dupes } ) -- 2.47.3