diff options
| author | mike bayer <mike_mp@zzzcomputing.com> | 2022-03-02 01:45:40 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit@ci3.zzzcomputing.com> | 2022-03-02 01:45:40 +0000 |
| commit | 7f1a3f22abffc1529100e14fcfd07a46a49fd44f (patch) | |
| tree | 9901a8c1d2bebca9f37131119874d7fb6e1979b3 /lib/sqlalchemy/engine/_py_row.py | |
| parent | 9e7c068d669b209713da62da5748579f92d98129 (diff) | |
| parent | a4bb502cf95ea3523e4d383c4377e50f402d7d52 (diff) | |
| download | sqlalchemy-7f1a3f22abffc1529100e14fcfd07a46a49fd44f.tar.gz | |
Merge "pep-484 for engine" into main
Diffstat (limited to 'lib/sqlalchemy/engine/_py_row.py')
| -rw-r--r-- | lib/sqlalchemy/engine/_py_row.py | 104 |
1 files changed, 58 insertions, 46 deletions
diff --git a/lib/sqlalchemy/engine/_py_row.py b/lib/sqlalchemy/engine/_py_row.py index a6d5b79d5..7cbac552f 100644 --- a/lib/sqlalchemy/engine/_py_row.py +++ b/lib/sqlalchemy/engine/_py_row.py @@ -1,26 +1,59 @@ from __future__ import annotations +import enum import operator +import typing +from typing import Any +from typing import Callable +from typing import Dict +from typing import Iterator +from typing import List +from typing import Optional +from typing import Tuple +from typing import Type +from typing import Union + +if typing.TYPE_CHECKING: + from .result import _KeyMapType + from .result import _KeyType + from .result import _ProcessorsType + from .result import _RawRowType + from .result import _TupleGetterType + from .result import ResultMetaData MD_INDEX = 0 # integer index in cursor.description -KEY_INTEGER_ONLY = 0 -"""__getitem__ only allows integer values and slices, raises TypeError - otherwise""" -KEY_OBJECTS_ONLY = 1 -"""__getitem__ only allows string/object values, raises TypeError otherwise""" +class _KeyStyle(enum.Enum): + KEY_INTEGER_ONLY = 0 + """__getitem__ only allows integer values and slices, raises TypeError + otherwise""" -sqlalchemy_engine_row = None + KEY_OBJECTS_ONLY = 1 + """__getitem__ only allows string/object values, raises TypeError + otherwise""" + + +KEY_INTEGER_ONLY, KEY_OBJECTS_ONLY = list(_KeyStyle) class BaseRow: - Row = None __slots__ = ("_parent", "_data", "_keymap", "_key_style") - def __init__(self, parent, processors, keymap, key_style, data): + _parent: ResultMetaData + _data: _RawRowType + _keymap: _KeyMapType + _key_style: _KeyStyle + + def __init__( + self, + parent: ResultMetaData, + processors: Optional[_ProcessorsType], + keymap: _KeyMapType, + key_style: _KeyStyle, + data: _RawRowType, + ): """Row objects are constructed by CursorResult objects.""" - object.__setattr__(self, "_parent", parent) if processors: @@ -41,68 +74,45 @@ class BaseRow: object.__setattr__(self, "_key_style", key_style) - def __reduce__(self): + def __reduce__(self) -> Tuple[Callable[..., BaseRow], Tuple[Any, ...]]: return ( rowproxy_reconstructor, (self.__class__, self.__getstate__()), ) - def __getstate__(self): + def __getstate__(self) -> Dict[str, Any]: return { "_parent": self._parent, "_data": self._data, "_key_style": self._key_style, } - def __setstate__(self, state): + def __setstate__(self, state: Dict[str, Any]) -> None: parent = state["_parent"] object.__setattr__(self, "_parent", parent) object.__setattr__(self, "_data", state["_data"]) object.__setattr__(self, "_keymap", parent._keymap) object.__setattr__(self, "_key_style", state["_key_style"]) - def _filter_on_values(self, filters): - global sqlalchemy_engine_row - if sqlalchemy_engine_row is None: - from sqlalchemy.engine.row import Row as sqlalchemy_engine_row - - return sqlalchemy_engine_row( - self._parent, - filters, - self._keymap, - self._key_style, - self._data, - ) - - def _values_impl(self): + def _values_impl(self) -> List[Any]: return list(self) - def __iter__(self): + def __iter__(self) -> Iterator[Any]: return iter(self._data) - def __len__(self): + def __len__(self) -> int: return len(self._data) - def __hash__(self): + def __hash__(self) -> int: return hash(self._data) - def _get_by_int_impl(self, key): + def _get_by_int_impl(self, key: Union[int, slice]) -> Any: return self._data[key] - def _get_by_key_impl(self, key): - # keep two isinstance since it's noticeably faster in the int case - if isinstance(key, int) or isinstance(key, slice): - return self._data[key] - - self._parent._raise_for_nonint(key) - - # The original 1.4 plan was that Row would not allow row["str"] - # access, however as the C extensions were inadvertently allowing - # this coupled with the fact that orm Session sets future=True, - # this allows a softer upgrade path. see #6218 - __getitem__ = _get_by_key_impl + if not typing.TYPE_CHECKING: + __getitem__ = _get_by_int_impl - def _get_by_key_impl_mapping(self, key): + def _get_by_key_impl_mapping(self, key: _KeyType) -> Any: try: rec = self._keymap[key] except KeyError as ke: @@ -116,7 +126,7 @@ class BaseRow: return self._data[mdindex] - def __getattr__(self, name): + def __getattr__(self, name: str) -> Any: try: return self._get_by_key_impl_mapping(name) except KeyError as e: @@ -125,13 +135,15 @@ class BaseRow: # This reconstructor is necessary so that pickles with the Cy extension or # without use the same Binary format. -def rowproxy_reconstructor(cls, state): +def rowproxy_reconstructor( + cls: Type[BaseRow], state: Dict[str, Any] +) -> BaseRow: obj = cls.__new__(cls) obj.__setstate__(state) return obj -def tuplegetter(*indexes): +def tuplegetter(*indexes: int) -> _TupleGetterType: it = operator.itemgetter(*indexes) if len(indexes) > 1: |
