Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
row.py401 linesDownload Raw Back to engine
1# engine/row.py
2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7
8"""Define row constructs including :class:`.Row`."""
9
10from __future__ import annotations
11
12from abc import ABC
13import collections.abc as collections_abc
14import operator
15import typing
16from typing import Any
17from typing import Callable
18from typing import Dict
19from typing import Generic
20from typing import Iterator
21from typing import List
22from typing import Mapping
23from typing import NoReturn
24from typing import Optional
25from typing import overload
26from typing import Sequence
27from typing import Tuple
28from typing import TYPE_CHECKING
29from typing import TypeVar
30from typing import Union
31
32from ..sql import util as sql_util
33from ..util import deprecated
34from ..util._has_cy import HAS_CYEXTENSION
35
36if TYPE_CHECKING or not HAS_CYEXTENSION:
37    from ._py_row import BaseRow as BaseRow
38else:
39    from sqlalchemy.cyextension.resultproxy import BaseRow as BaseRow
40
41if TYPE_CHECKING:
42    from .result import _KeyType
43    from .result import _ProcessorsType
44    from .result import RMKeyView
45
46_T = TypeVar("_T", bound=Any)
47_TP = TypeVar("_TP", bound=Tuple[Any, ...])
48
49
50class Row(BaseRow, Sequence[Any], Generic[_TP]):
51    """Represent a single result row.
52
53    The :class:`.Row` object represents a row of a database result.  It is
54    typically associated in the 1.x series of SQLAlchemy with the
55    :class:`_engine.CursorResult` object, however is also used by the ORM for
56    tuple-like results as of SQLAlchemy 1.4.
57
58    The :class:`.Row` object seeks to act as much like a Python named
59    tuple as possible.   For mapping (i.e. dictionary) behavior on a row,
60    such as testing for containment of keys, refer to the :attr:`.Row._mapping`
61    attribute.
62
63    .. seealso::
64
65        :ref:`tutorial_selecting_data` - includes examples of selecting
66        rows from SELECT statements.
67
68    .. versionchanged:: 1.4
69
70        Renamed ``RowProxy`` to :class:`.Row`. :class:`.Row` is no longer a
71        "proxy" object in that it contains the final form of data within it,
72        and now acts mostly like a named tuple. Mapping-like functionality is
73        moved to the :attr:`.Row._mapping` attribute. See
74        :ref:`change_4710_core` for background on this change.
75
76    """
77
78    __slots__ = ()
79
80    def __setattr__(self, name: str, value: Any) -> NoReturn:
81        raise AttributeError("can't set attribute")
82
83    def __delattr__(self, name: str) -> NoReturn:
84        raise AttributeError("can't delete attribute")
85
86    def _tuple(self) -> _TP:
87        """Return a 'tuple' form of this :class:`.Row`.
88
89        At runtime, this method returns "self"; the :class:`.Row` object is
90        already a named tuple. However, at the typing level, if this
91        :class:`.Row` is typed, the "tuple" return type will be a :pep:`484`
92        ``Tuple`` datatype that contains typing information about individual
93        elements, supporting typed unpacking and attribute access.
94
95        .. versionadded:: 2.0.19 - The :meth:`.Row._tuple` method supersedes
96           the previous :meth:`.Row.tuple` method, which is now underscored
97           to avoid name conflicts with column names in the same way as other
98           named-tuple methods on :class:`.Row`.
99
100        .. seealso::
101
102            :attr:`.Row._t` - shorthand attribute notation
103
104            :meth:`.Result.tuples`
105
106
107        """
108        return self  # type: ignore
109
110    @deprecated(
111        "2.0.19",
112        "The :meth:`.Row.tuple` method is deprecated in favor of "
113        ":meth:`.Row._tuple`; all :class:`.Row` "
114        "methods and library-level attributes are intended to be underscored "
115        "to avoid name conflicts.  Please use :meth:`Row._tuple`.",
116    )
117    def tuple(self) -> _TP:
118        """Return a 'tuple' form of this :class:`.Row`.
119
120        .. versionadded:: 2.0
121
122        """
123        return self._tuple()
124
125    @property
126    def _t(self) -> _TP:
127        """A synonym for :meth:`.Row._tuple`.
128
129        .. versionadded:: 2.0.19 - The :attr:`.Row._t` attribute supersedes
130           the previous :attr:`.Row.t` attribute, which is now underscored
131           to avoid name conflicts with column names in the same way as other
132           named-tuple methods on :class:`.Row`.
133
134        .. seealso::
135
136            :attr:`.Result.t`
137        """
138        return self  # type: ignore
139
140    @property
141    @deprecated(
142        "2.0.19",
143        "The :attr:`.Row.t` attribute is deprecated in favor of "
144        ":attr:`.Row._t`; all :class:`.Row` "
145        "methods and library-level attributes are intended to be underscored "
146        "to avoid name conflicts.  Please use :attr:`Row._t`.",
147    )
148    def t(self) -> _TP:
149        """A synonym for :meth:`.Row._tuple`.
150
151        .. versionadded:: 2.0
152
153        """
154        return self._t
155
156    @property
157    def _mapping(self) -> RowMapping:
158        """Return a :class:`.RowMapping` for this :class:`.Row`.
159
160        This object provides a consistent Python mapping (i.e. dictionary)
161        interface for the data contained within the row.   The :class:`.Row`
162        by itself behaves like a named tuple.
163
164        .. seealso::
165
166            :attr:`.Row._fields`
167
168        .. versionadded:: 1.4
169
170        """
171        return RowMapping(self._parent, None, self._key_to_index, self._data)
172
173    def _filter_on_values(
174        self, processor: Optional[_ProcessorsType]
175    ) -> Row[Any]:
176        return Row(self._parent, processor, self._key_to_index, self._data)
177
178    if not TYPE_CHECKING:
179
180        def _special_name_accessor(name: str) -> Any:
181            """Handle ambiguous names such as "count" and "index" """
182
183            @property
184            def go(self: Row) -> Any:
185                if self._parent._has_key(name):
186                    return self.__getattr__(name)
187                else:
188
189                    def meth(*arg: Any, **kw: Any) -> Any:
190                        return getattr(collections_abc.Sequence, name)(
191                            self, *arg, **kw
192                        )
193
194                    return meth
195
196            return go
197
198        count = _special_name_accessor("count")
199        index = _special_name_accessor("index")
200
201    def __contains__(self, key: Any) -> bool:
202        return key in self._data
203
204    def _op(self, other: Any, op: Callable[[Any, Any], bool]) -> bool:
205        return (
206            op(self._to_tuple_instance(), other._to_tuple_instance())
207            if isinstance(other, Row)
208            else op(self._to_tuple_instance(), other)
209        )
210
211    __hash__ = BaseRow.__hash__
212
213    if TYPE_CHECKING:
214
215        @overload
216        def __getitem__(self, index: int) -> Any: ...
217
218        @overload
219        def __getitem__(self, index: slice) -> Sequence[Any]: ...
220
221        def __getitem__(self, index: Union[int, slice]) -> Any: ...
222
223    def __lt__(self, other: Any) -> bool:
224        return self._op(other, operator.lt)
225
226    def __le__(self, other: Any) -> bool:
227        return self._op(other, operator.le)
228
229    def __ge__(self, other: Any) -> bool:
230        return self._op(other, operator.ge)
231
232    def __gt__(self, other: Any) -> bool:
233        return self._op(other, operator.gt)
234
235    def __eq__(self, other: Any) -> bool:
236        return self._op(other, operator.eq)
237
238    def __ne__(self, other: Any) -> bool:
239        return self._op(other, operator.ne)
240
241    def __repr__(self) -> str:
242        return repr(sql_util._repr_row(self))
243
244    @property
245    def _fields(self) -> Tuple[str, ...]:
246        """Return a tuple of string keys as represented by this
247        :class:`.Row`.
248
249        The keys can represent the labels of the columns returned by a core
250        statement or the names of the orm classes returned by an orm
251        execution.
252
253        This attribute is analogous to the Python named tuple ``._fields``
254        attribute.
255
256        .. versionadded:: 1.4
257
258        .. seealso::
259
260            :attr:`.Row._mapping`
261
262        """
263        return tuple([k for k in self._parent.keys if k is not None])
264
265    def _asdict(self) -> Dict[str, Any]:
266        """Return a new dict which maps field names to their corresponding
267        values.
268
269        This method is analogous to the Python named tuple ``._asdict()``
270        method, and works by applying the ``dict()`` constructor to the
271        :attr:`.Row._mapping` attribute.
272
273        .. versionadded:: 1.4
274
275        .. seealso::
276
277            :attr:`.Row._mapping`
278
279        """
280        return dict(self._mapping)
281
282
283BaseRowProxy = BaseRow
284RowProxy = Row
285
286
287class ROMappingView(ABC):
288    __slots__ = ()
289
290    _items: Sequence[Any]
291    _mapping: Mapping["_KeyType", Any]
292
293    def __init__(
294        self, mapping: Mapping["_KeyType", Any], items: Sequence[Any]
295    ):
296        self._mapping = mapping  # type: ignore[misc]
297        self._items = items  # type: ignore[misc]
298
299    def __len__(self) -> int:
300        return len(self._items)
301
302    def __repr__(self) -> str:
303        return "{0.__class__.__name__}({0._mapping!r})".format(self)
304
305    def __iter__(self) -> Iterator[Any]:
306        return iter(self._items)
307
308    def __contains__(self, item: Any) -> bool:
309        return item in self._items
310
311    def __eq__(self, other: Any) -> bool:
312        return list(other) == list(self)
313
314    def __ne__(self, other: Any) -> bool:
315        return list(other) != list(self)
316
317
318class ROMappingKeysValuesView(
319    ROMappingView, typing.KeysView["_KeyType"], typing.ValuesView[Any]
320):
321    __slots__ = ("_items",)  # mapping slot is provided by KeysView
322
323
324class ROMappingItemsView(ROMappingView, typing.ItemsView["_KeyType", Any]):
325    __slots__ = ("_items",)  # mapping slot is provided by ItemsView
326
327
328class RowMapping(BaseRow, typing.Mapping["_KeyType", Any]):
329    """A ``Mapping`` that maps column names and objects to :class:`.Row`
330    values.
331
332    The :class:`.RowMapping` is available from a :class:`.Row` via the
333    :attr:`.Row._mapping` attribute, as well as from the iterable interface
334    provided by the :class:`.MappingResult` object returned by the
335    :meth:`_engine.Result.mappings` method.
336
337    :class:`.RowMapping` supplies Python mapping (i.e. dictionary) access to
338    the  contents of the row.   This includes support for testing of
339    containment of specific keys (string column names or objects), as well
340    as iteration of keys, values, and items::
341
342        for row in result:
343            if "a" in row._mapping:
344                print("Column 'a': %s" % row._mapping["a"])
345
346            print("Column b: %s" % row._mapping[table.c.b])
347
348    .. versionadded:: 1.4 The :class:`.RowMapping` object replaces the
349       mapping-like access previously provided by a database result row,
350       which now seeks to behave mostly like a named tuple.
351
352    """
353
354    __slots__ = ()
355
356    if TYPE_CHECKING:
357
358        def __getitem__(self, key: _KeyType) -> Any: ...
359
360    else:
361        __getitem__ = BaseRow._get_by_key_impl_mapping
362
363    def _values_impl(self) -> List[Any]:
364        return list(self._data)
365
366    def __iter__(self) -> Iterator[str]:
367        return (k for k in self._parent.keys if k is not None)
368
369    def __len__(self) -> int:
370        return len(self._data)
371
372    def __contains__(self, key: object) -> bool:
373        return self._parent._has_key(key)
374
375    def __repr__(self) -> str:
376        return repr(dict(self))
377
378    def items(self) -> ROMappingItemsView:
379        """Return a view of key/value tuples for the elements in the
380        underlying :class:`.Row`.
381
382        """
383        return ROMappingItemsView(
384            self, [(key, self[key]) for key in self.keys()]
385        )
386
387    def keys(self) -> RMKeyView:
388        """Return a view of 'keys' for string column names represented
389        by the underlying :class:`.Row`.
390
391        """
392
393        return self._parent.keys
394
395    def values(self) -> ROMappingKeysValuesView:
396        """Return a view of values for the values represented in the
397        underlying :class:`.Row`.
398
399        """
400        return ROMappingKeysValuesView(self, self._values_impl())
401 
codekingpro/portable-devtools · Team Ai