--- /dev/null
+.. change::
+ :tags: bug, engine
+ :tickets: 6074
+
+ The Python ``namedtuple()`` has the behavior such that the names ``count``
+ and ``index`` will be served as tuple values if the named tuple includes
+ those names; if they are absent, then their behavior as methods of
+ ``collections.abc.Sequence`` is maintained. Therefore the
+ :class:`_result.Row` and :class:`_result.LegacyRow` classes have been fixed
+ so that they work in this same way, maintaining the expected behavior for
+ database rows that have columns named "index" or "count".
self._data,
)
+ def _special_name_accessor(name):
+ """Handle ambiguous names such as "count" and "index" """
+
+ @property
+ def go(self):
+ if self._parent._has_key(name):
+ return self.__getattr__(name)
+ else:
+
+ def meth(*arg, **kw):
+ return getattr(collections_abc.Sequence, name)(
+ self, *arg, **kw
+ )
+
+ return meth
+
+ return go
+
+ count = _special_name_accessor("count")
+ index = _special_name_accessor("index")
+
def __contains__(self, key):
return key in self._data
from sqlalchemy.engine import cursor as _cursor
from sqlalchemy.engine import default
from sqlalchemy.engine import Row
+from sqlalchemy.engine.result import SimpleResultMetaData
+from sqlalchemy.engine.row import LegacyRow
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql import ColumnElement
from sqlalchemy.sql import expression
)
is_true(isinstance(row, collections_abc.Sequence))
+ @testing.combinations((Row,), (LegacyRow,))
+ def test_row_special_names(self, row_cls):
+ metadata = SimpleResultMetaData(["key", "count", "index"])
+ row = row_cls(
+ metadata,
+ [None, None, None],
+ metadata._keymap,
+ Row._default_key_style,
+ ["kv", "cv", "iv"],
+ )
+ is_true(isinstance(row, collections_abc.Sequence))
+
+ eq_(row.key, "kv")
+ eq_(row.count, "cv")
+ eq_(row.index, "iv")
+
+ if isinstance(row, LegacyRow):
+ eq_(row["count"], "cv")
+ eq_(row["index"], "iv")
+
+ eq_(row._mapping["count"], "cv")
+ eq_(row._mapping["index"], "iv")
+
+ metadata = SimpleResultMetaData(["key", "q", "p"])
+
+ row = row_cls(
+ metadata,
+ [None, None, None],
+ metadata._keymap,
+ Row._default_key_style,
+ ["kv", "cv", "iv"],
+ )
+ is_true(isinstance(row, collections_abc.Sequence))
+
+ eq_(row.key, "kv")
+ eq_(row.q, "cv")
+ eq_(row.p, "iv")
+ eq_(row.index("cv"), 1)
+ eq_(row.count("cv"), 1)
+ eq_(row.count("x"), 0)
+
def test_row_is_hashable(self):
row = Row(